From 3b40a1d839a9bb1226da14017a6cc98abfae6a7a Mon Sep 17 00:00:00 2001 From: kahirokunn Date: Fri, 25 Oct 2024 14:18:00 +0900 Subject: [PATCH] add support for KEDA HTTPScaledObjects via HTTPScaledObjectReconciler Signed-off-by: kahirokunn --- artifacts/flagger/account.yaml | 13 + artifacts/flagger/crd.yaml | 33 + charts/flagger/Chart.yaml | 4 +- charts/flagger/crds/crd.yaml | 33 + charts/flagger/templates/rbac.yaml | 13 + docs/gitbook/SUMMARY.md | 1 + kustomize/base/flagger/crd.yaml | 33 + kustomize/base/flagger/rbac.yaml | 13 + pkg/apis/flagger/v1beta1/canary.go | 40 + .../flagger/v1beta1/zz_generated.deepcopy.go | 42 ++ pkg/apis/http/register.go | 5 + pkg/apis/http/v1alpha1/condition_types.go | 88 +++ pkg/apis/http/v1alpha1/doc.go | 5 + .../http/v1alpha1/httpscaledobject_types.go | 183 +++++ .../http/v1alpha1/httpscalingset_defaults.go | 149 ++++ .../http/v1alpha1/httpscalingset_types.go | 233 ++++++ pkg/apis/http/v1alpha1/register.go | 56 ++ pkg/apis/http/v1alpha1/version.go | 30 + .../http/v1alpha1/zz_generated.deepcopy.go | 687 ++++++++++++++++++ pkg/canary/deployment_controller.go | 7 + pkg/canary/factory.go | 9 + pkg/canary/http_scaled_object_reconciler.go | 166 +++++ pkg/client/clientset/versioned/clientset.go | 13 + .../versioned/fake/clientset_generated.go | 7 + .../clientset/versioned/fake/register.go | 2 + .../clientset/versioned/scheme/register.go | 2 + .../http/v1alpha1/clusterhttpscalingset.go | 195 +++++ .../versioned/typed/http/v1alpha1/doc.go | 20 + .../versioned/typed/http/v1alpha1/fake/doc.go | 20 + .../fake/fake_clusterhttpscalingset.go | 141 ++++ .../http/v1alpha1/fake/fake_http_client.go | 48 ++ .../v1alpha1/fake/fake_httpscaledobject.go | 141 ++++ .../http/v1alpha1/fake/fake_httpscalingset.go | 141 ++++ .../http/v1alpha1/generated_expansion.go | 25 + .../typed/http/v1alpha1/http_client.go | 117 +++ .../typed/http/v1alpha1/httpscaledobject.go | 195 +++++ .../typed/http/v1alpha1/httpscalingset.go | 195 +++++ .../informers/externalversions/factory.go | 6 + .../informers/externalversions/generic.go | 13 +- .../externalversions/http/interface.go | 46 ++ .../http/v1alpha1/clusterhttpscalingset.go | 90 +++ .../http/v1alpha1/httpscaledobject.go | 90 +++ .../http/v1alpha1/httpscalingset.go | 90 +++ .../http/v1alpha1/interface.go | 59 ++ .../http/v1alpha1/clusterhttpscalingset.go | 99 +++ .../http/v1alpha1/expansion_generated.go | 43 ++ .../listers/http/v1alpha1/httpscaledobject.go | 99 +++ .../listers/http/v1alpha1/httpscalingset.go | 99 +++ pkg/router/factory.go | 20 +- pkg/router/gateway_api.go | 104 ++- pkg/router/kubernetes_default.go | 4 + 51 files changed, 3928 insertions(+), 39 deletions(-) create mode 100644 pkg/apis/http/register.go create mode 100644 pkg/apis/http/v1alpha1/condition_types.go create mode 100644 pkg/apis/http/v1alpha1/doc.go create mode 100644 pkg/apis/http/v1alpha1/httpscaledobject_types.go create mode 100644 pkg/apis/http/v1alpha1/httpscalingset_defaults.go create mode 100644 pkg/apis/http/v1alpha1/httpscalingset_types.go create mode 100644 pkg/apis/http/v1alpha1/register.go create mode 100644 pkg/apis/http/v1alpha1/version.go create mode 100644 pkg/apis/http/v1alpha1/zz_generated.deepcopy.go create mode 100644 pkg/canary/http_scaled_object_reconciler.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/clusterhttpscalingset.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/doc.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/fake/doc.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_clusterhttpscalingset.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_http_client.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_httpscaledobject.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_httpscalingset.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/generated_expansion.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/http_client.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/httpscaledobject.go create mode 100644 pkg/client/clientset/versioned/typed/http/v1alpha1/httpscalingset.go create mode 100644 pkg/client/informers/externalversions/http/interface.go create mode 100644 pkg/client/informers/externalversions/http/v1alpha1/clusterhttpscalingset.go create mode 100644 pkg/client/informers/externalversions/http/v1alpha1/httpscaledobject.go create mode 100644 pkg/client/informers/externalversions/http/v1alpha1/httpscalingset.go create mode 100644 pkg/client/informers/externalversions/http/v1alpha1/interface.go create mode 100644 pkg/client/listers/http/v1alpha1/clusterhttpscalingset.go create mode 100644 pkg/client/listers/http/v1alpha1/expansion_generated.go create mode 100644 pkg/client/listers/http/v1alpha1/httpscaledobject.go create mode 100644 pkg/client/listers/http/v1alpha1/httpscalingset.go diff --git a/artifacts/flagger/account.yaml b/artifacts/flagger/account.yaml index ae07a7f89..79f0aae14 100644 --- a/artifacts/flagger/account.yaml +++ b/artifacts/flagger/account.yaml @@ -239,6 +239,19 @@ rules: - update - patch - delete + - apiGroups: + - http.keda.sh + resources: + - httpscaledobjects + - httpscaledobjects/finalizers + verbs: + - get + - list + - watch + - create + - update + - patch + - delete - apiGroups: - apisix.apache.org resources: diff --git a/artifacts/flagger/crd.yaml b/artifacts/flagger/crd.yaml index 99940df06..20277fa4a 100644 --- a/artifacts/flagger/crd.yaml +++ b/artifacts/flagger/crd.yaml @@ -119,6 +119,7 @@ spec: enum: - HorizontalPodAutoscaler - ScaledObject + - HTTPScaledObject name: type: string primaryScalerQueries: @@ -132,6 +133,38 @@ spec: type: number maxReplicas: type: number + canaryInterceptorProxyService: + type: object + description: Specify this service if you want to change the Canary interceptor proxy service from its default value. + properties: + name: + default: keda-http-add-on-interceptor-proxy + maxLength: 253 + minLength: 1 + type: string + namespace: + default: keda + maxLength: 63 + minLength: 1 + type: string + primaryScalingSet: + type: object + description: |- + PrimaryScalingSet to be used for primary HTTPScaledObject, if empty, default interceptor and scaler will be used. + properties: + kind: + description: Kind of the resource being referred to. Defaults to HTTPScalingSet. + enum: + - HTTPScalingSet + - ClusterHTTPScalingSet + type: string + name: + description: Name of the scaling set + type: string + namespace: + maxLength: 63 + minLength: 1 + type: string ingressRef: description: Ingress selector type: object diff --git a/charts/flagger/Chart.yaml b/charts/flagger/Chart.yaml index 51b82c21a..87f396b38 100644 --- a/charts/flagger/Chart.yaml +++ b/charts/flagger/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v1 name: flagger -version: 1.38.0 -appVersion: 1.38.0 +version: 1.39.0 +appVersion: 1.39.0 kubeVersion: ">=1.19.0-0" engine: gotpl description: Flagger is a progressive delivery operator for Kubernetes diff --git a/charts/flagger/crds/crd.yaml b/charts/flagger/crds/crd.yaml index 99940df06..20277fa4a 100644 --- a/charts/flagger/crds/crd.yaml +++ b/charts/flagger/crds/crd.yaml @@ -119,6 +119,7 @@ spec: enum: - HorizontalPodAutoscaler - ScaledObject + - HTTPScaledObject name: type: string primaryScalerQueries: @@ -132,6 +133,38 @@ spec: type: number maxReplicas: type: number + canaryInterceptorProxyService: + type: object + description: Specify this service if you want to change the Canary interceptor proxy service from its default value. + properties: + name: + default: keda-http-add-on-interceptor-proxy + maxLength: 253 + minLength: 1 + type: string + namespace: + default: keda + maxLength: 63 + minLength: 1 + type: string + primaryScalingSet: + type: object + description: |- + PrimaryScalingSet to be used for primary HTTPScaledObject, if empty, default interceptor and scaler will be used. + properties: + kind: + description: Kind of the resource being referred to. Defaults to HTTPScalingSet. + enum: + - HTTPScalingSet + - ClusterHTTPScalingSet + type: string + name: + description: Name of the scaling set + type: string + namespace: + maxLength: 63 + minLength: 1 + type: string ingressRef: description: Ingress selector type: object diff --git a/charts/flagger/templates/rbac.yaml b/charts/flagger/templates/rbac.yaml index ae9c70155..6085fd8b3 100644 --- a/charts/flagger/templates/rbac.yaml +++ b/charts/flagger/templates/rbac.yaml @@ -247,6 +247,19 @@ rules: - update - patch - delete + - apiGroups: + - http.keda.sh + resources: + - httpscaledobjects + - httpscaledobjects/finalizers + verbs: + - get + - list + - watch + - create + - update + - patch + - delete - apiGroups: - apisix.apache.org resources: diff --git a/docs/gitbook/SUMMARY.md b/docs/gitbook/SUMMARY.md index 868549d81..31f39c064 100644 --- a/docs/gitbook/SUMMARY.md +++ b/docs/gitbook/SUMMARY.md @@ -38,6 +38,7 @@ * [Blue/Green Deployments](tutorials/kubernetes-blue-green.md) * [Canary analysis with Prometheus Operator](tutorials/prometheus-operator.md) * [Canary analysis with KEDA ScaledObjects](tutorials/keda-scaledobject.md) +* [Canary analysis with KEDA HTTPScaledObjects](tutorials/keda-httpscaledobject.md) * [Zero downtime deployments](tutorials/zero-downtime-deployments.md) ## Dev diff --git a/kustomize/base/flagger/crd.yaml b/kustomize/base/flagger/crd.yaml index 99940df06..20277fa4a 100644 --- a/kustomize/base/flagger/crd.yaml +++ b/kustomize/base/flagger/crd.yaml @@ -119,6 +119,7 @@ spec: enum: - HorizontalPodAutoscaler - ScaledObject + - HTTPScaledObject name: type: string primaryScalerQueries: @@ -132,6 +133,38 @@ spec: type: number maxReplicas: type: number + canaryInterceptorProxyService: + type: object + description: Specify this service if you want to change the Canary interceptor proxy service from its default value. + properties: + name: + default: keda-http-add-on-interceptor-proxy + maxLength: 253 + minLength: 1 + type: string + namespace: + default: keda + maxLength: 63 + minLength: 1 + type: string + primaryScalingSet: + type: object + description: |- + PrimaryScalingSet to be used for primary HTTPScaledObject, if empty, default interceptor and scaler will be used. + properties: + kind: + description: Kind of the resource being referred to. Defaults to HTTPScalingSet. + enum: + - HTTPScalingSet + - ClusterHTTPScalingSet + type: string + name: + description: Name of the scaling set + type: string + namespace: + maxLength: 63 + minLength: 1 + type: string ingressRef: description: Ingress selector type: object diff --git a/kustomize/base/flagger/rbac.yaml b/kustomize/base/flagger/rbac.yaml index 7e46cd99c..9b7c1e210 100644 --- a/kustomize/base/flagger/rbac.yaml +++ b/kustomize/base/flagger/rbac.yaml @@ -229,6 +229,19 @@ rules: - update - patch - delete + - apiGroups: + - http.keda.sh + resources: + - httpscaledobjects + - httpscaledobjects/finalizers + verbs: + - get + - list + - watch + - create + - update + - patch + - delete - apiGroups: - apisix.apache.org resources: diff --git a/pkg/apis/flagger/v1beta1/canary.go b/pkg/apis/flagger/v1beta1/canary.go index 93fe004ed..6e8c2df8b 100644 --- a/pkg/apis/flagger/v1beta1/canary.go +++ b/pkg/apis/flagger/v1beta1/canary.go @@ -21,6 +21,7 @@ import ( "time" "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1" + http "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -454,6 +455,35 @@ type LocalObjectReference struct { Name string `json:"name"` } +// CanaryInterceptorProxyService specifies the service if you want to change +// the Canary interceptor proxy service from its default value. +type CanaryInterceptorProxyService struct { + // Name of the canary interceptor proxy service. + // Defaults to "keda-http-add-on-interceptor-proxy". + // +optional + Name string `json:"name,omitempty"` + + // Namespace of the canary interceptor proxy service. + // Defaults to "keda". + // +optional + Namespace string `json:"namespace,omitempty"` +} + +// PrimaryScalingSet defines the desired scaling set to be used +type PrimaryScalingSet struct { + // Kind of the resource being referred to. Defaults to HTTPScalingSet. + // +optional + Kind http.ScalingSetKind `json:"kind,omitempty"` + + // Name of the scaling set + Name string `json:"name,omitempty"` + + // Namespace of the scaling set + // Defaults to "keda". + // +optional + Namespace string `json:"namespace,omitempty"` +} + type AutoscalerRefernce struct { // API version of the scaler // +required @@ -476,6 +506,16 @@ type AutoscalerRefernce struct { // autoscaler replicas. // +optional PrimaryScalerReplicas *ScalerReplicas `json:"primaryScalerReplicas,omitempty"` + + // CanaryInterceptorProxyService specifies the service if you want to change + // the Canary interceptor proxy service from its default value. + // +optional + CanaryInterceptorProxyService *CanaryInterceptorProxyService `json:"canaryInterceptorProxyService,omitempty"` + + // PrimaryScalingSet is the scaling set to be used for the primary + // scaler, if a scaler supports scaling using queries. + // +optional + PrimaryScalingSet *PrimaryScalingSet `json:"primaryScalingSet,omitempty"` } // ScalerReplicas holds overrides for autoscaler replicas diff --git a/pkg/apis/flagger/v1beta1/zz_generated.deepcopy.go b/pkg/apis/flagger/v1beta1/zz_generated.deepcopy.go index 340fc0439..25651167e 100644 --- a/pkg/apis/flagger/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/flagger/v1beta1/zz_generated.deepcopy.go @@ -166,6 +166,16 @@ func (in *AutoscalerRefernce) DeepCopyInto(out *AutoscalerRefernce) { *out = new(ScalerReplicas) (*in).DeepCopyInto(*out) } + if in.CanaryInterceptorProxyService != nil { + in, out := &in.CanaryInterceptorProxyService, &out.CanaryInterceptorProxyService + *out = new(CanaryInterceptorProxyService) + **out = **in + } + if in.PrimaryScalingSet != nil { + in, out := &in.PrimaryScalingSet, &out.PrimaryScalingSet + *out = new(PrimaryScalingSet) + **out = **in + } return } @@ -304,6 +314,22 @@ func (in *CanaryCondition) DeepCopy() *CanaryCondition { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CanaryInterceptorProxyService) DeepCopyInto(out *CanaryInterceptorProxyService) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryInterceptorProxyService. +func (in *CanaryInterceptorProxyService) DeepCopy() *CanaryInterceptorProxyService { + if in == nil { + return nil + } + out := new(CanaryInterceptorProxyService) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CanaryList) DeepCopyInto(out *CanaryList) { *out = *in @@ -868,6 +894,22 @@ func (in *MetricTemplateStatus) DeepCopy() *MetricTemplateStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrimaryScalingSet) DeepCopyInto(out *PrimaryScalingSet) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrimaryScalingSet. +func (in *PrimaryScalingSet) DeepCopy() *PrimaryScalingSet { + if in == nil { + return nil + } + out := new(PrimaryScalingSet) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ScalerReplicas) DeepCopyInto(out *ScalerReplicas) { *out = *in diff --git a/pkg/apis/http/register.go b/pkg/apis/http/register.go new file mode 100644 index 000000000..5ee2620f0 --- /dev/null +++ b/pkg/apis/http/register.go @@ -0,0 +1,5 @@ +package http + +const ( + GroupName = "http.keda.sh" +) diff --git a/pkg/apis/http/v1alpha1/condition_types.go b/pkg/apis/http/v1alpha1/condition_types.go new file mode 100644 index 000000000..114265d37 --- /dev/null +++ b/pkg/apis/http/v1alpha1/condition_types.go @@ -0,0 +1,88 @@ +package v1alpha1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// +kubebuilder:validation:Enum=Ready + +// HTTPScaledObjectCreationStatus describes the creation status +// of the scaler's additional resources such as Services, Ingresses and Deployments +type HTTPScaledObjectCreationStatus string + +const ( + // Ready indicates the object is fully created + Ready HTTPScaledObjectCreationStatus = "Ready" +) + +// +kubebuilder:validation:Enum=ErrorCreatingAppScaledObject;AppScaledObjectCreated;TerminatingResources;AppScaledObjectTerminated;AppScaledObjectTerminationError;PendingCreation;HTTPScaledObjectIsReady; + +// HTTPScaledObjectConditionReason describes the reason why the condition transitioned +type HTTPScaledObjectConditionReason string + +const ( + ErrorCreatingAppScaledObject HTTPScaledObjectConditionReason = "ErrorCreatingAppScaledObject" + AppScaledObjectCreated HTTPScaledObjectConditionReason = "AppScaledObjectCreated" + TerminatingResources HTTPScaledObjectConditionReason = "TerminatingResources" + AppScaledObjectTerminated HTTPScaledObjectConditionReason = "AppScaledObjectTerminated" + AppScaledObjectTerminationError HTTPScaledObjectConditionReason = "AppScaledObjectTerminationError" + PendingCreation HTTPScaledObjectConditionReason = "PendingCreation" + HTTPScaledObjectIsReady HTTPScaledObjectConditionReason = "HTTPScaledObjectIsReady" +) + +// HTTPScaledObjectCondition stores the condition state +type HTTPScaledObjectCondition struct { + // Timestamp of the condition + // +optional + Timestamp string `json:"timestamp" description:"Timestamp of this condition"` + // Type of condition + // +required + Type HTTPScaledObjectCreationStatus `json:"type" description:"type of status condition"` + // Status of the condition, one of True, False, Unknown. + // +required + Status metav1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"` + // Reason for the condition's last transition. + // +optional + Reason HTTPScaledObjectConditionReason `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"` + // Message indicating details about the transition. + // +optional + Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"` +} + +type Conditions []HTTPScaledObjectCondition + +// GetReadyCondition returns Condition of type Ready +func (c *Conditions) GetReadyCondition() HTTPScaledObjectCondition { + if *c == nil { + c = GetInitializedConditions() + } + return c.getCondition(Ready) +} + +// GetInitializedConditions returns Conditions initialized to the default -> Status: Unknown +func GetInitializedConditions() *Conditions { + return &Conditions{{Type: Ready, Status: metav1.ConditionUnknown}} +} + +// IsTrue is true if the condition is True +func (c *HTTPScaledObjectCondition) IsTrue() bool { + if c == nil { + return false + } + return c.Status == metav1.ConditionTrue +} + +// IsFalse is true if the condition is False +func (c *HTTPScaledObjectCondition) IsFalse() bool { + if c == nil { + return false + } + return c.Status == metav1.ConditionFalse +} + +func (c Conditions) getCondition(conditionType HTTPScaledObjectCreationStatus) HTTPScaledObjectCondition { + for i := range c { + if c[i].Type == conditionType { + return c[i] + } + } + return HTTPScaledObjectCondition{} +} diff --git a/pkg/apis/http/v1alpha1/doc.go b/pkg/apis/http/v1alpha1/doc.go new file mode 100644 index 000000000..47b747cf1 --- /dev/null +++ b/pkg/apis/http/v1alpha1/doc.go @@ -0,0 +1,5 @@ +// +k8s:deepcopy-gen=package + +// Package v1 is the v1 version of the API. +// +groupName=http.keda.sh +package v1alpha1 diff --git a/pkg/apis/http/v1alpha1/httpscaledobject_types.go b/pkg/apis/http/v1alpha1/httpscaledobject_types.go new file mode 100644 index 000000000..f1f61b04f --- /dev/null +++ b/pkg/apis/http/v1alpha1/httpscaledobject_types.go @@ -0,0 +1,183 @@ +/* +Copyright 2023 The KEDA Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ScalingSetKind string + +const ( + HTTPScalingSetKind ScalingSetKind = "HTTPScalingSet" + ClusterHTTPScalingSetKind ScalingSetKind = "ClusterHTTPScalingSet" +) + +// ScaleTargetRef contains all the details about an HTTP application to scale and route to +type ScaleTargetRef struct { + // +optional + Name string `json:"name"` + // +optional + APIVersion string `json:"apiVersion,omitempty"` + // +optional + Kind string `json:"kind,omitempty"` + // The name of the service to route to + Service string `json:"service"` + // The port to route to + Port int32 `json:"port"` +} + +// ReplicaStruct contains the minimum and maximum amount of replicas to have in the deployment +type ReplicaStruct struct { + // Minimum amount of replicas to have in the deployment (Default 0) + Min *int32 `json:"min,omitempty" description:"Minimum amount of replicas to have in the deployment (Default 0)"` + // Maximum amount of replicas to have in the deployment (Default 100) + Max *int32 `json:"max,omitempty" description:"Maximum amount of replicas to have in the deployment (Default 100)"` +} + +// ScalingMetricSpec contains the scaling calculation type +type ScalingMetricSpec struct { + // Scaling based on concurrent requests for a given target + Concurrency *ConcurrencyMetricSpec `json:"concurrency,omitempty" description:"Scaling based on concurrent requests for a given target. 'concurrency' and 'rate' are mutually exclusive."` + // Scaling based the average rate during an specific time window for a given target + Rate *RateMetricSpec `json:"requestRate,omitempty" description:"Scaling based the average rate during an specific time window for a given target. 'concurrency' and 'rate' are mutually exclusive."` +} + +// ConcurrencyMetricSpec defines the concurrency scaling +type ConcurrencyMetricSpec struct { + // Target value for rate scaling + // +kubebuilder:default=100 + // +optional + TargetValue int `json:"targetValue" description:"Target value for concurrency scaling"` +} + +// RateMetricSpec defines the concurrency scaling +type RateMetricSpec struct { + // Target value for rate scaling + // +kubebuilder:default=100 + // +optional + TargetValue int `json:"targetValue" description:"Target value for rate scaling"` + // Time window for rate calculation + // +kubebuilder:default="1m" + // +optional + Window metav1.Duration `json:"window" description:"Time window for rate calculation"` + // Time granularity for rate calculation + // +kubebuilder:default="1s" + // +optional + Granularity metav1.Duration `json:"granularity" description:"Time granularity for rate calculation"` +} + +// HTTPSalingSetTargetRef defines the desired scaling set to be used +type HTTPSalingSetTargetRef struct { + // Name of the scaling set + Name string `json:"name,omitempty"` + // Kind of the resource being referred to. Defaults to HTTPScalingSet. + // +kubebuilder:validation:Enum=HTTPScalingSet;ClusterHTTPScalingSet + // +optional + Kind ScalingSetKind `json:"kind,omitempty"` +} + +func (so *HTTPScaledObjectSpec) GetHTTPSalingSetTargetRef() HTTPSalingSetTargetRef { + r := HTTPSalingSetTargetRef{} + if so.ScalingSet == nil { + return r + } + + r.Name = so.ScalingSet.Name + r.Kind = ClusterHTTPScalingSetKind + if so.ScalingSet.Kind != "" { + r.Kind = so.ScalingSet.Kind + } + return r +} + +// HTTPScaledObjectSpec defines the desired state of HTTPScaledObject +type HTTPScaledObjectSpec struct { + // ScalingSet to be used for this HTTPScaledObject, if empty, default + // interceptor and scaler will be used + // +optional + ScalingSet *HTTPSalingSetTargetRef `json:"scalingSet,omitempty"` + // The hosts to route. All requests which the "Host" header + // matches any .spec.hosts (and the Request Target matches any + // .spec.pathPrefixes) will be routed to the Service and Port specified in + // the scaleTargetRef. + Hosts []string `json:"hosts,omitempty"` + // The paths to route. All requests which the Request Target matches any + // .spec.pathPrefixes (and the "Host" header matches any .spec.hosts) + // will be routed to the Service and Port specified in + // the scaleTargetRef. + // +optional + PathPrefixes []string `json:"pathPrefixes,omitempty"` + // The name of the deployment to route HTTP requests to (and to autoscale). + ScaleTargetRef ScaleTargetRef `json:"scaleTargetRef"` + // (optional) Replica information + // +optional + Replicas *ReplicaStruct `json:"replicas,omitempty"` + // (optional) DEPRECATED (use ScalingMetric instead) Target metric value + // +optional + TargetPendingRequests *int32 `json:"targetPendingRequests,omitempty" description:"The target metric value for the HPA (Default 100)"` + // (optional) Cooldown period value + // +optional + CooldownPeriod *int32 `json:"scaledownPeriod,omitempty" description:"Cooldown period (seconds) for resources to scale down (Default 300)"` + // (optional) Configuration for the metric used for scaling + // +optional + ScalingMetric *ScalingMetricSpec `json:"scalingMetric,omitempty" description:"Configuration for the metric used for scaling. If empty 'concurrency' will be used"` +} + +// HTTPScaledObjectStatus defines the observed state of HTTPScaledObject +type HTTPScaledObjectStatus struct { + // TargetWorkload reflects details about the scaled workload. + // +optional + TargetWorkload string `json:"targetWorkload,omitempty" description:"It reflects details about the scaled workload"` + // TargetService reflects details about the scaled service. + // +optional + TargetService string `json:"targetService,omitempty" description:"It reflects details about the scaled service"` + // Conditions of the operator + Conditions Conditions `json:"conditions,omitempty" description:"List of auditable conditions of the operator"` +} + +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:printcolumn:name="TargetWorkload",type="string",JSONPath=".status.targetWorkload" +// +kubebuilder:printcolumn:name="TargetService",type="string",JSONPath=".status.targetService" +// +kubebuilder:printcolumn:name="MinReplicas",type="integer",JSONPath=".spec.replicas.min" +// +kubebuilder:printcolumn:name="MaxReplicas",type="integer",JSONPath=".spec.replicas.max" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:printcolumn:name="Active",type="string",JSONPath=".status.conditions[?(@.type==\"HTTPScaledObjectIsReady\")].status" +// +kubebuilder:resource:shortName=httpso +// +kubebuilder:subresource:status + +// HTTPScaledObject is the Schema for the httpscaledobjects API +type HTTPScaledObject struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec HTTPScaledObjectSpec `json:"spec"` + Status HTTPScaledObjectStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// HTTPScaledObjectList contains a list of HTTPScaledObject +type HTTPScaledObjectList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []HTTPScaledObject `json:"items"` +} diff --git a/pkg/apis/http/v1alpha1/httpscalingset_defaults.go b/pkg/apis/http/v1alpha1/httpscalingset_defaults.go new file mode 100644 index 000000000..0f8a4f6e1 --- /dev/null +++ b/pkg/apis/http/v1alpha1/httpscalingset_defaults.go @@ -0,0 +1,149 @@ +/* +Copyright 2024 The KEDA Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "fmt" +) + +var ( + interceptorImage = fmt.Sprintf("ghcr.io/kedacore/http-add-on-interceptor:%s", Version()) + scalerImage = fmt.Sprintf("ghcr.io/kedacore/http-add-on-scaler:%s", Version()) +) + +func (c *HTTPInterceptorSpec) GetProxyPort() int32 { + if c.Config == nil || c.Config.ProxyPort == nil { + return 8080 + } + return *c.Config.ProxyPort +} + +func (c *HTTPInterceptorSpec) GetAdminPort() int32 { + if c.Config == nil || c.Config.AdminPort == nil { + return 9090 + } + return *c.Config.AdminPort +} +func (c *HTTPInterceptorSpec) GetConnectTimeout() string { + if c.Config == nil || c.Config.ConnectTimeout == nil { + return "500ms" + } + return *c.Config.ConnectTimeout +} +func (c *HTTPInterceptorSpec) GetHeaderTimeout() string { + if c.Config == nil || c.Config.HeaderTimeout == nil { + return "500ms" + } + return *c.Config.HeaderTimeout +} +func (c *HTTPInterceptorSpec) GetWaitTimeout() string { + if c.Config == nil || c.Config.WaitTimeout == nil { + return "1500ms" + } + return *c.Config.WaitTimeout +} +func (c *HTTPInterceptorSpec) GetIdleConnTimeout() string { + if c.Config == nil || c.Config.IdleConnTimeout == nil { + return "90s" + } + return *c.Config.IdleConnTimeout +} +func (c *HTTPInterceptorSpec) GetTLSHandshakeTimeout() string { + if c.Config == nil || c.Config.TLSHandshakeTimeout == nil { + return "10s" + } + return *c.Config.TLSHandshakeTimeout +} +func (c *HTTPInterceptorSpec) GetExpectContinueTimeout() string { + if c.Config == nil || c.Config.ExpectContinueTimeout == nil { + return "1s" + } + return *c.Config.ExpectContinueTimeout +} +func (c *HTTPInterceptorSpec) GetForceHTTP2() bool { + if c.Config == nil || c.Config.ForceHTTP2 == nil { + return false + } + return *c.Config.ForceHTTP2 +} +func (c *HTTPInterceptorSpec) GetKeepAlive() string { + if c.Config == nil || c.Config.KeepAlive == nil { + return "1s" + } + return *c.Config.KeepAlive +} +func (c *HTTPInterceptorSpec) GetMaxIdleConns() int { + if c.Config == nil || c.Config.MaxIdleConns == nil { + return 100 + } + return *c.Config.MaxIdleConns +} +func (c *HTTPInterceptorSpec) GetPollingInterval() int { + if c.Config == nil || c.Config.PollingInterval == nil { + return 1000 + } + return *c.Config.PollingInterval +} + +func (c *HTTPInterceptorSpec) GetImage() string { + if c.Image == nil { + return interceptorImage + } + return *c.Image +} + +func (c *HTTPInterceptorSpec) GetLabels() map[string]string { + if c.Labels == nil { + return map[string]string{} + } + return c.Labels +} + +func (c *HTTPInterceptorSpec) GetAnnotations() map[string]string { + if c.Annotations == nil { + return map[string]string{} + } + return c.Annotations +} + +func (c *HTTPScalerSpec) GetPort() int32 { + if c.Config.Port == nil { + return 9090 + } + return *c.Config.Port +} + +func (c *HTTPScalerSpec) GetImage() string { + if c.Image == nil { + return scalerImage + } + return *c.Image +} + +func (c *HTTPScalerSpec) GetLabels() map[string]string { + if c.Labels == nil { + return map[string]string{} + } + return c.Labels +} + +func (c *HTTPScalerSpec) GetAnnotations() map[string]string { + if c.Annotations == nil { + return map[string]string{} + } + return c.Annotations +} diff --git a/pkg/apis/http/v1alpha1/httpscalingset_types.go b/pkg/apis/http/v1alpha1/httpscalingset_types.go new file mode 100644 index 000000000..bedf621cd --- /dev/null +++ b/pkg/apis/http/v1alpha1/httpscalingset_types.go @@ -0,0 +1,233 @@ +/* +Copyright 2024 The KEDA Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// HTTPInterceptorScalingSpec defines the desired state of Interceptor autoscaling +type HTTPInterceptorScalingSpec struct { + // +kubebuilder:default=3 + // +optional + // Minimum replicas for the interceptor + MinReplicas int `json:"minReplicas"` + // +kubebuilder:default=100 + // +optional + // Maximum replicas for the interceptor + MaxReplicas int `json:"maxReplicas"` + // +kubebuilder:default=100 + // +optional + // Target concurrent requests + Target int `json:"target"` +} + +// HTTPInterceptorConfigurationSpec defines the desired state of Interceptor configuration +type HTTPInterceptorConfigurationSpec struct { + // +optional + // Port to be used for proxy operations + ProxyPort *int32 `json:"proxyPort,omitempty"` + // +optional + // Port to be used for admin operations + AdminPort *int32 `json:"adminPort,omitempty"` + // +optional + // Timeout for establishing the connection + ConnectTimeout *string `json:"connectTimeout,omitempty"` + // +optional + // How long to wait between when the HTTP request + // is sent to the backing app and when response headers need to arrive + HeaderTimeout *string `json:"headerTimeout,omitempty"` + // +optional + // How long to wait for the backing workload + // to have 1 or more replicas before connecting and sending the HTTP request. + WaitTimeout *string `json:"waitTimeout,omitempty"` + // +optional + // Timeout after which a connection in the interceptor's + // internal connection pool will be closed + IdleConnTimeout *string `json:"idleConnTimeout,omitempty"` + // +optional + // Max amount of time the interceptor will + // wait to establish a TLS connection + TLSHandshakeTimeout *string `json:"handshakeTimeout,omitempty"` + // +optional + // Max amount of time the interceptor will wait + // after sending request headers if the server returned an Expect: 100-continue + // header + ExpectContinueTimeout *string `json:"expectContinueTimeout,omitempty"` + // +optional + // Try to force HTTP2 for all requests + ForceHTTP2 *bool `json:"forceHTTP2,omitempty"` + // +optional + // Interval between keepalive probes + KeepAlive *string `json:"keepAlive,omitempty"` + // +optional + // Max number of connections that can be idle in the + // interceptor's internal connection pool + MaxIdleConns *int `json:"maxIdleConnections,omitempty"` + // +optional + // The interceptor has an internal process that periodically fetches the state + // of endpoints that is running the servers it forwards to. + // This is the interval (in milliseconds) representing how often to do a fetch + PollingInterval *int `json:"pollingInterval,omitempty"` +} + +// HTTPInterceptorSpec defines the desired state of Interceptor component +type HTTPInterceptorSpec struct { + // +optional + // Traffic configuration + Config *HTTPInterceptorConfigurationSpec `json:"config,omitempty"` + // Number of replicas for the interceptor + Replicas *int32 `json:"replicas,omitempty"` + // Container image name. + // +optional + Image *string `json:"image,omitempty"` + // ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. + // If specified, these secrets will be passed to individual puller implementations for them to use. + // More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod + // +optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + // Autoscaling options for the interceptor + Autoscaling *HTTPInterceptorScalingSpec `json:"autoscaling,omitempty"` + // Compute Resources required by this interceptor. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + // +optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + // Map of string keys and values that can be used to organize and categorize + // (scope and select) objects. May match selectors of replication controllers + // and services. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels + // +optional + Labels map[string]string `json:"labels,omitempty"` + // Annotations is an unstructured key value map stored with a resource that may be + // set by external tools to store and retrieve arbitrary metadata. They are not + // queryable and should be preserved when modifying objects. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations + // +optional + Annotations map[string]string `json:"annotations,omitempty"` + // +kubebuilder:default=default + // +optional + // Name of the service account to be used + ServiceAccountName string `json:"serviceAccountName"` +} + +// HTTPScalerConfigurationSpec defines the desired state of scaler configuration +type HTTPScalerConfigurationSpec struct { + // +kubebuilder:default=9090 + // +optional + // Port to be used for proxy operations + Port *int32 `json:"port,omitempty"` +} + +// HTTPScalerSpec defines the desired state of Scaler component +type HTTPScalerSpec struct { + // +kubebuilder:default={} + // +optional + // Traffic configuration + Config HTTPScalerConfigurationSpec `json:"config,omitempty"` + // Number of replicas for the interceptor + Replicas *int32 `json:"replicas,omitempty"` + // Container image name. + // +optional + Image *string `json:"image,omitempty"` + // ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. + // If specified, these secrets will be passed to individual puller implementations for them to use. + // More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod + // +optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + // Compute Resources required by this scaler. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + // +optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + // Map of string keys and values that can be used to organize and categorize + // (scope and select) objects. May match selectors of replication controllers + // and services. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels + // +optional + Labels map[string]string `json:"labels,omitempty"` + // Annotations is an unstructured key value map stored with a resource that may be + // set by external tools to store and retrieve arbitrary metadata. They are not + // queryable and should be preserved when modifying objects. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations + // +optional + Annotations map[string]string `json:"annotations,omitempty"` + // +kubebuilder:default=default + // +optional + // Name of the service account to be used + ServiceAccountName string `json:"serviceAccountName"` +} + +// HTTPScalingSetSpec defines the desired state of HTTPScalingSet +type HTTPScalingSetSpec struct { + Interceptor HTTPInterceptorSpec `json:"interceptor"` + Scaler HTTPScalerSpec `json:"scaler"` +} + +// HTTPScalingSetStatus defines the observed state of HTTPScalingSet +type HTTPScalingSetStatus struct{} + +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:shortName=ss +// +kubebuilder:subresource:status + +// HTTPScalingSet is the Schema for the httpscalingset API +type HTTPScalingSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec HTTPScalingSetSpec `json:"spec,omitempty"` + Status HTTPScalingSetStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// HTTPScalingSetList contains a list of HTTPScalingSetList +type HTTPScalingSetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []HTTPScalingSet `json:"items"` +} + +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:shortName=css,scope=Cluster +// +kubebuilder:subresource:status + +// ClusterHTTPScalingSet is the Schema for the cluster httpscalingset API +type ClusterHTTPScalingSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec HTTPScalingSetSpec `json:"spec,omitempty"` + Status HTTPScalingSetStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// ClusterHTTPScalingSetList contains a list of ClusterHTTPScalingSet +type ClusterHTTPScalingSetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ClusterHTTPScalingSet `json:"items"` +} diff --git a/pkg/apis/http/v1alpha1/register.go b/pkg/apis/http/v1alpha1/register.go new file mode 100644 index 000000000..6af69e227 --- /dev/null +++ b/pkg/apis/http/v1alpha1/register.go @@ -0,0 +1,56 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "github.com/fluxcd/flagger/pkg/apis/http" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: http.GroupName, Version: "v1alpha1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &HTTPScaledObject{}, + &HTTPScaledObjectList{}, + &HTTPScalingSet{}, + &HTTPScalingSetList{}, + &ClusterHTTPScalingSet{}, + &ClusterHTTPScalingSetList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/http/v1alpha1/version.go b/pkg/apis/http/v1alpha1/version.go new file mode 100644 index 000000000..af463fcc2 --- /dev/null +++ b/pkg/apis/http/v1alpha1/version.go @@ -0,0 +1,30 @@ +package v1alpha1 + +import ( + "fmt" + "runtime" + + "github.com/go-logr/logr" +) + +var ( + version = "main" + gitCommit string +) + +// Version returns the current git SHA of commit the binary was built from +func Version() string { + return version +} + +// GitCommit stores the current commit hash +func GitCommit() string { + return gitCommit +} + +func PrintComponentInfo(logger logr.Logger, component string) { + logger.Info(fmt.Sprintf("%s Version: %s", component, Version())) + logger.Info(fmt.Sprintf("%s Commit: %s", component, GitCommit())) + logger.Info(fmt.Sprintf("Go Version: %s", runtime.Version())) + logger.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH)) +} diff --git a/pkg/apis/http/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/http/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..35358fa54 --- /dev/null +++ b/pkg/apis/http/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,687 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterHTTPScalingSet) DeepCopyInto(out *ClusterHTTPScalingSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterHTTPScalingSet. +func (in *ClusterHTTPScalingSet) DeepCopy() *ClusterHTTPScalingSet { + if in == nil { + return nil + } + out := new(ClusterHTTPScalingSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterHTTPScalingSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterHTTPScalingSetList) DeepCopyInto(out *ClusterHTTPScalingSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterHTTPScalingSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterHTTPScalingSetList. +func (in *ClusterHTTPScalingSetList) DeepCopy() *ClusterHTTPScalingSetList { + if in == nil { + return nil + } + out := new(ClusterHTTPScalingSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterHTTPScalingSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConcurrencyMetricSpec) DeepCopyInto(out *ConcurrencyMetricSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConcurrencyMetricSpec. +func (in *ConcurrencyMetricSpec) DeepCopy() *ConcurrencyMetricSpec { + if in == nil { + return nil + } + out := new(ConcurrencyMetricSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in Conditions) DeepCopyInto(out *Conditions) { + { + in := &in + *out = make(Conditions, len(*in)) + copy(*out, *in) + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Conditions. +func (in Conditions) DeepCopy() Conditions { + if in == nil { + return nil + } + out := new(Conditions) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPInterceptorConfigurationSpec) DeepCopyInto(out *HTTPInterceptorConfigurationSpec) { + *out = *in + if in.ProxyPort != nil { + in, out := &in.ProxyPort, &out.ProxyPort + *out = new(int32) + **out = **in + } + if in.AdminPort != nil { + in, out := &in.AdminPort, &out.AdminPort + *out = new(int32) + **out = **in + } + if in.ConnectTimeout != nil { + in, out := &in.ConnectTimeout, &out.ConnectTimeout + *out = new(string) + **out = **in + } + if in.HeaderTimeout != nil { + in, out := &in.HeaderTimeout, &out.HeaderTimeout + *out = new(string) + **out = **in + } + if in.WaitTimeout != nil { + in, out := &in.WaitTimeout, &out.WaitTimeout + *out = new(string) + **out = **in + } + if in.IdleConnTimeout != nil { + in, out := &in.IdleConnTimeout, &out.IdleConnTimeout + *out = new(string) + **out = **in + } + if in.TLSHandshakeTimeout != nil { + in, out := &in.TLSHandshakeTimeout, &out.TLSHandshakeTimeout + *out = new(string) + **out = **in + } + if in.ExpectContinueTimeout != nil { + in, out := &in.ExpectContinueTimeout, &out.ExpectContinueTimeout + *out = new(string) + **out = **in + } + if in.ForceHTTP2 != nil { + in, out := &in.ForceHTTP2, &out.ForceHTTP2 + *out = new(bool) + **out = **in + } + if in.KeepAlive != nil { + in, out := &in.KeepAlive, &out.KeepAlive + *out = new(string) + **out = **in + } + if in.MaxIdleConns != nil { + in, out := &in.MaxIdleConns, &out.MaxIdleConns + *out = new(int) + **out = **in + } + if in.PollingInterval != nil { + in, out := &in.PollingInterval, &out.PollingInterval + *out = new(int) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPInterceptorConfigurationSpec. +func (in *HTTPInterceptorConfigurationSpec) DeepCopy() *HTTPInterceptorConfigurationSpec { + if in == nil { + return nil + } + out := new(HTTPInterceptorConfigurationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPInterceptorScalingSpec) DeepCopyInto(out *HTTPInterceptorScalingSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPInterceptorScalingSpec. +func (in *HTTPInterceptorScalingSpec) DeepCopy() *HTTPInterceptorScalingSpec { + if in == nil { + return nil + } + out := new(HTTPInterceptorScalingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPInterceptorSpec) DeepCopyInto(out *HTTPInterceptorSpec) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = new(HTTPInterceptorConfigurationSpec) + (*in).DeepCopyInto(*out) + } + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + if in.Image != nil { + in, out := &in.Image, &out.Image + *out = new(string) + **out = **in + } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]v1.LocalObjectReference, len(*in)) + copy(*out, *in) + } + if in.Autoscaling != nil { + in, out := &in.Autoscaling, &out.Autoscaling + *out = new(HTTPInterceptorScalingSpec) + **out = **in + } + in.Resources.DeepCopyInto(&out.Resources) + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPInterceptorSpec. +func (in *HTTPInterceptorSpec) DeepCopy() *HTTPInterceptorSpec { + if in == nil { + return nil + } + out := new(HTTPInterceptorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPSalingSetTargetRef) DeepCopyInto(out *HTTPSalingSetTargetRef) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPSalingSetTargetRef. +func (in *HTTPSalingSetTargetRef) DeepCopy() *HTTPSalingSetTargetRef { + if in == nil { + return nil + } + out := new(HTTPSalingSetTargetRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScaledObject) DeepCopyInto(out *HTTPScaledObject) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScaledObject. +func (in *HTTPScaledObject) DeepCopy() *HTTPScaledObject { + if in == nil { + return nil + } + out := new(HTTPScaledObject) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPScaledObject) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScaledObjectCondition) DeepCopyInto(out *HTTPScaledObjectCondition) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScaledObjectCondition. +func (in *HTTPScaledObjectCondition) DeepCopy() *HTTPScaledObjectCondition { + if in == nil { + return nil + } + out := new(HTTPScaledObjectCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScaledObjectList) DeepCopyInto(out *HTTPScaledObjectList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]HTTPScaledObject, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScaledObjectList. +func (in *HTTPScaledObjectList) DeepCopy() *HTTPScaledObjectList { + if in == nil { + return nil + } + out := new(HTTPScaledObjectList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPScaledObjectList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScaledObjectSpec) DeepCopyInto(out *HTTPScaledObjectSpec) { + *out = *in + if in.ScalingSet != nil { + in, out := &in.ScalingSet, &out.ScalingSet + *out = new(HTTPSalingSetTargetRef) + **out = **in + } + if in.Hosts != nil { + in, out := &in.Hosts, &out.Hosts + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.PathPrefixes != nil { + in, out := &in.PathPrefixes, &out.PathPrefixes + *out = make([]string, len(*in)) + copy(*out, *in) + } + out.ScaleTargetRef = in.ScaleTargetRef + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(ReplicaStruct) + (*in).DeepCopyInto(*out) + } + if in.TargetPendingRequests != nil { + in, out := &in.TargetPendingRequests, &out.TargetPendingRequests + *out = new(int32) + **out = **in + } + if in.CooldownPeriod != nil { + in, out := &in.CooldownPeriod, &out.CooldownPeriod + *out = new(int32) + **out = **in + } + if in.ScalingMetric != nil { + in, out := &in.ScalingMetric, &out.ScalingMetric + *out = new(ScalingMetricSpec) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScaledObjectSpec. +func (in *HTTPScaledObjectSpec) DeepCopy() *HTTPScaledObjectSpec { + if in == nil { + return nil + } + out := new(HTTPScaledObjectSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScaledObjectStatus) DeepCopyInto(out *HTTPScaledObjectStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(Conditions, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScaledObjectStatus. +func (in *HTTPScaledObjectStatus) DeepCopy() *HTTPScaledObjectStatus { + if in == nil { + return nil + } + out := new(HTTPScaledObjectStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScalerConfigurationSpec) DeepCopyInto(out *HTTPScalerConfigurationSpec) { + *out = *in + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScalerConfigurationSpec. +func (in *HTTPScalerConfigurationSpec) DeepCopy() *HTTPScalerConfigurationSpec { + if in == nil { + return nil + } + out := new(HTTPScalerConfigurationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScalerSpec) DeepCopyInto(out *HTTPScalerSpec) { + *out = *in + in.Config.DeepCopyInto(&out.Config) + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + if in.Image != nil { + in, out := &in.Image, &out.Image + *out = new(string) + **out = **in + } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]v1.LocalObjectReference, len(*in)) + copy(*out, *in) + } + in.Resources.DeepCopyInto(&out.Resources) + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScalerSpec. +func (in *HTTPScalerSpec) DeepCopy() *HTTPScalerSpec { + if in == nil { + return nil + } + out := new(HTTPScalerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScalingSet) DeepCopyInto(out *HTTPScalingSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScalingSet. +func (in *HTTPScalingSet) DeepCopy() *HTTPScalingSet { + if in == nil { + return nil + } + out := new(HTTPScalingSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPScalingSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScalingSetList) DeepCopyInto(out *HTTPScalingSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]HTTPScalingSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScalingSetList. +func (in *HTTPScalingSetList) DeepCopy() *HTTPScalingSetList { + if in == nil { + return nil + } + out := new(HTTPScalingSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPScalingSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScalingSetSpec) DeepCopyInto(out *HTTPScalingSetSpec) { + *out = *in + in.Interceptor.DeepCopyInto(&out.Interceptor) + in.Scaler.DeepCopyInto(&out.Scaler) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScalingSetSpec. +func (in *HTTPScalingSetSpec) DeepCopy() *HTTPScalingSetSpec { + if in == nil { + return nil + } + out := new(HTTPScalingSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPScalingSetStatus) DeepCopyInto(out *HTTPScalingSetStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPScalingSetStatus. +func (in *HTTPScalingSetStatus) DeepCopy() *HTTPScalingSetStatus { + if in == nil { + return nil + } + out := new(HTTPScalingSetStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RateMetricSpec) DeepCopyInto(out *RateMetricSpec) { + *out = *in + out.Window = in.Window + out.Granularity = in.Granularity + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateMetricSpec. +func (in *RateMetricSpec) DeepCopy() *RateMetricSpec { + if in == nil { + return nil + } + out := new(RateMetricSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReplicaStruct) DeepCopyInto(out *ReplicaStruct) { + *out = *in + if in.Min != nil { + in, out := &in.Min, &out.Min + *out = new(int32) + **out = **in + } + if in.Max != nil { + in, out := &in.Max, &out.Max + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicaStruct. +func (in *ReplicaStruct) DeepCopy() *ReplicaStruct { + if in == nil { + return nil + } + out := new(ReplicaStruct) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScaleTargetRef) DeepCopyInto(out *ScaleTargetRef) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScaleTargetRef. +func (in *ScaleTargetRef) DeepCopy() *ScaleTargetRef { + if in == nil { + return nil + } + out := new(ScaleTargetRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScalingMetricSpec) DeepCopyInto(out *ScalingMetricSpec) { + *out = *in + if in.Concurrency != nil { + in, out := &in.Concurrency, &out.Concurrency + *out = new(ConcurrencyMetricSpec) + **out = **in + } + if in.Rate != nil { + in, out := &in.Rate, &out.Rate + *out = new(RateMetricSpec) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScalingMetricSpec. +func (in *ScalingMetricSpec) DeepCopy() *ScalingMetricSpec { + if in == nil { + return nil + } + out := new(ScalingMetricSpec) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/canary/deployment_controller.go b/pkg/canary/deployment_controller.go index 708f4babe..7a7a4775f 100644 --- a/pkg/canary/deployment_controller.go +++ b/pkg/canary/deployment_controller.go @@ -207,6 +207,13 @@ func (c *DeploymentController) ScaleFromZero(cd *flaggerv1.Canary) error { replicas = so.Spec.MinReplicaCount } } + } else if cd.Spec.AutoscalerRef.Kind == "HTTPScaledObject" { + httpso, err := c.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Get(context.TODO(), cd.Spec.AutoscalerRef.Name, metav1.GetOptions{}) + if err == nil { + if httpso.Spec.Replicas.Min != nil && *httpso.Spec.Replicas.Min > 1 { + replicas = httpso.Spec.Replicas.Min + } + } } } diff --git a/pkg/canary/factory.go b/pkg/canary/factory.go index ec3924f4a..498719f98 100644 --- a/pkg/canary/factory.go +++ b/pkg/canary/factory.go @@ -99,11 +99,20 @@ func (factory *Factory) ScalerReconciler(kind string) ScalerReconciler { includeLabelPrefix: factory.includeLabelPrefix, } + httpsoReconciler := &HTTPScaledObjectReconciler{ + logger: factory.logger, + kubeClient: factory.kubeClient, + flaggerClient: factory.flaggerClient, + includeLabelPrefix: factory.includeLabelPrefix, + } + switch kind { case "HorizontalPodAutoscaler": return hpaReconciler case "ScaledObject": return soReconciler + case "HTTPScaledObject": + return httpsoReconciler default: return nil } diff --git a/pkg/canary/http_scaled_object_reconciler.go b/pkg/canary/http_scaled_object_reconciler.go new file mode 100644 index 000000000..59747b1aa --- /dev/null +++ b/pkg/canary/http_scaled_object_reconciler.go @@ -0,0 +1,166 @@ +package canary + +import ( + "context" + "fmt" + + "go.uber.org/zap" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/util/retry" + + flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1" + http "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + keda "github.com/fluxcd/flagger/pkg/apis/keda/v1alpha1" + clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned" + "github.com/google/go-cmp/cmp" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// HTTPScaledObjectReconciler is a ScalerReconciler that reconciles KEDA HTTPScaledObjects. +type HTTPScaledObjectReconciler struct { + kubeClient kubernetes.Interface + flaggerClient clientset.Interface + logger *zap.SugaredLogger + includeLabelPrefix []string +} + +func (sor *HTTPScaledObjectReconciler) ReconcilePrimaryScaler(cd *flaggerv1.Canary, init bool) error { + if cd.Spec.AutoscalerRef != nil { + if err := sor.reconcilePrimaryScaler(cd, init); err != nil { + return err + } + } + return nil +} + +func (sor *HTTPScaledObjectReconciler) reconcilePrimaryScaler(cd *flaggerv1.Canary, init bool) error { + primaryName := fmt.Sprintf("%s-primary", cd.Spec.TargetRef.Name) + targetSo, err := sor.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Get(context.TODO(), cd.Spec.AutoscalerRef.Name, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("Keda HTTPScaledObject %s.%s get query error: %w", + cd.Spec.AutoscalerRef.Name, cd.Namespace, err) + } + targetSoClone := targetSo.DeepCopy() + primaryServiceName := fmt.Sprintf("%s-primary", targetSoClone.Spec.ScaleTargetRef.Service) + + httpsoSpec := http.HTTPScaledObjectSpec{ + Hosts: targetSoClone.Spec.Hosts, + PathPrefixes: targetSoClone.Spec.PathPrefixes, + ScaleTargetRef: http.ScaleTargetRef{ + Name: primaryName, + APIVersion: targetSoClone.Spec.ScaleTargetRef.APIVersion, + Kind: targetSoClone.Spec.ScaleTargetRef.Kind, + Service: primaryServiceName, + Port: targetSoClone.Spec.ScaleTargetRef.Port, + }, + Replicas: targetSoClone.Spec.Replicas, + TargetPendingRequests: targetSoClone.Spec.TargetPendingRequests, + CooldownPeriod: targetSoClone.Spec.CooldownPeriod, + ScalingMetric: targetSoClone.Spec.ScalingMetric, + } + + if scalingSet := cd.Spec.AutoscalerRef.PrimaryScalingSet; scalingSet != nil { + httpsoSpec.ScalingSet = &http.HTTPSalingSetTargetRef{ + Name: scalingSet.Name, + Kind: scalingSet.Kind, + } + } + + if replicas := cd.Spec.AutoscalerRef.PrimaryScalerReplicas; replicas != nil { + if minReplicas := replicas.MinReplicas; minReplicas != nil { + httpsoSpec.Replicas.Min = minReplicas + } + if maxReplicas := replicas.MaxReplicas; maxReplicas != nil { + httpsoSpec.Replicas.Max = maxReplicas + } + } + + primarySoName := fmt.Sprintf("%s-primary", cd.Spec.AutoscalerRef.Name) + primarySo, err := sor.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Get(context.TODO(), primarySoName, metav1.GetOptions{}) + if errors.IsNotFound(err) { + primarySo = &http.HTTPScaledObject{ + ObjectMeta: makeObjectMeta(primarySoName, targetSoClone.Labels, cd), + Spec: httpsoSpec, + } + _, err = sor.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Create(context.TODO(), primarySo, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("creating Keda HTTPScaledObject %s.%s failed: %w", + primarySo.Name, primarySo.Namespace, err) + } + sor.logger.With("canary", fmt.Sprintf("%s.%s", cd.Name, cd.Namespace)).Infof( + "Keda HTTPScaledObject %s.%s created", primarySo.GetName(), cd.Namespace) + return nil + } else if err != nil { + return fmt.Errorf("Keda HTTPScaledObject %s.%s get query failed: %w", + primarySo.Name, primarySo.Namespace, err) + } + + if primarySo != nil && !init { + if diff := cmp.Diff(httpsoSpec, primarySo.Spec); diff != "" { + err = retry.RetryOnConflict(retry.DefaultBackoff, func() error { + primarySo, err := sor.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Get(context.TODO(), primarySoName, metav1.GetOptions{}) + if err != nil { + return err + } + primarySoClone := primarySo.DeepCopy() + primarySoClone.Spec = httpsoSpec + + filteredAnnotations := includeLabelsByPrefix(primarySo.Annotations, sor.includeLabelPrefix) + primarySoClone.Annotations = filteredAnnotations + filteredLabels := includeLabelsByPrefix(primarySo.ObjectMeta.Labels, sor.includeLabelPrefix) + primarySoClone.Labels = filteredLabels + + _, err = sor.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Update(context.TODO(), primarySoClone, metav1.UpdateOptions{}) + return err + }) + if err != nil { + return fmt.Errorf("updating HTTPScaledObject %s.%s failed: %w", primarySoName, cd.Namespace, err) + } + } + } + return nil +} + +func (sor *HTTPScaledObjectReconciler) PauseTargetScaler(cd *flaggerv1.Canary) error { + err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + so, err := sor.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Get(context.TODO(), cd.Spec.AutoscalerRef.Name, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("Keda HTTPScaledObject %s.%s get query error: %w", + cd.Spec.AutoscalerRef.Name, cd.Namespace, err) + } + soClone := so.DeepCopy() + + if soClone.ObjectMeta.Annotations == nil { + soClone.ObjectMeta.Annotations = make(map[string]string) + } + soClone.ObjectMeta.Annotations[keda.PausedReplicasAnnotation] = "0" + + _, err = sor.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Update(context.TODO(), soClone, metav1.UpdateOptions{}) + return err + }) + + return err +} + +func (sor *HTTPScaledObjectReconciler) ResumeTargetScaler(cd *flaggerv1.Canary) error { + err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + so, err := sor.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Get(context.TODO(), cd.Spec.AutoscalerRef.Name, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("Keda HTTPScaledObject %s.%s get query error: %w", + cd.Spec.AutoscalerRef.Name, cd.Namespace, err) + } + soClone := so.DeepCopy() + + if soClone.ObjectMeta.Annotations != nil { + if _, ok := soClone.ObjectMeta.Annotations[keda.PausedReplicasAnnotation]; ok { + delete(soClone.Annotations, keda.PausedReplicasAnnotation) + } + } + + _, err = sor.flaggerClient.HttpV1alpha1().HTTPScaledObjects(cd.Namespace).Update(context.TODO(), soClone, metav1.UpdateOptions{}) + return err + }) + + return err +} diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index bde8b926e..555c290fc 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -30,6 +30,7 @@ import ( gatewayapiv1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gatewayapi/v1" gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gatewayapi/v1beta1" gloov1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gloo/v1" + httpv1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/http/v1alpha1" networkingv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1beta1" kedav1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/keda/v1alpha1" kumav1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/kuma/v1alpha1" @@ -53,6 +54,7 @@ type Interface interface { GatewayapiV1beta1() gatewayapiv1beta1.GatewayapiV1beta1Interface GatewayapiV1() gatewayapiv1.GatewayapiV1Interface GlooV1() gloov1.GlooV1Interface + HttpV1alpha1() httpv1alpha1.HttpV1alpha1Interface NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface KedaV1alpha1() kedav1alpha1.KedaV1alpha1Interface KumaV1alpha1() kumav1alpha1.KumaV1alpha1Interface @@ -74,6 +76,7 @@ type Clientset struct { gatewayapiV1beta1 *gatewayapiv1beta1.GatewayapiV1beta1Client gatewayapiV1 *gatewayapiv1.GatewayapiV1Client glooV1 *gloov1.GlooV1Client + httpV1alpha1 *httpv1alpha1.HttpV1alpha1Client networkingV1beta1 *networkingv1beta1.NetworkingV1beta1Client kedaV1alpha1 *kedav1alpha1.KedaV1alpha1Client kumaV1alpha1 *kumav1alpha1.KumaV1alpha1Client @@ -124,6 +127,11 @@ func (c *Clientset) GlooV1() gloov1.GlooV1Interface { return c.glooV1 } +// HttpV1alpha1 retrieves the HttpV1alpha1Client +func (c *Clientset) HttpV1alpha1() httpv1alpha1.HttpV1alpha1Interface { + return c.httpV1alpha1 +} + // NetworkingV1beta1 retrieves the NetworkingV1beta1Client func (c *Clientset) NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface { return c.networkingV1beta1 @@ -240,6 +248,10 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, if err != nil { return nil, err } + cs.httpV1alpha1, err = httpv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } cs.networkingV1beta1, err = networkingv1beta1.NewForConfigAndClient(&configShallowCopy, httpClient) if err != nil { return nil, err @@ -301,6 +313,7 @@ func New(c rest.Interface) *Clientset { cs.gatewayapiV1beta1 = gatewayapiv1beta1.New(c) cs.gatewayapiV1 = gatewayapiv1.New(c) cs.glooV1 = gloov1.New(c) + cs.httpV1alpha1 = httpv1alpha1.New(c) cs.networkingV1beta1 = networkingv1beta1.New(c) cs.kedaV1alpha1 = kedav1alpha1.New(c) cs.kumaV1alpha1 = kumav1alpha1.New(c) diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index c0fe650b6..2f2256259 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -36,6 +36,8 @@ import ( fakegatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gatewayapi/v1beta1/fake" gloov1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gloo/v1" fakegloov1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gloo/v1/fake" + httpv1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/http/v1alpha1" + fakehttpv1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/http/v1alpha1/fake" networkingv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1beta1" fakenetworkingv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1beta1/fake" kedav1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/keda/v1alpha1" @@ -149,6 +151,11 @@ func (c *Clientset) GlooV1() gloov1.GlooV1Interface { return &fakegloov1.FakeGlooV1{Fake: &c.Fake} } +// HttpV1alpha1 retrieves the HttpV1alpha1Client +func (c *Clientset) HttpV1alpha1() httpv1alpha1.HttpV1alpha1Interface { + return &fakehttpv1alpha1.FakeHttpV1alpha1{Fake: &c.Fake} +} + // NetworkingV1beta1 retrieves the NetworkingV1beta1Client func (c *Clientset) NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface { return &fakenetworkingv1beta1.FakeNetworkingV1beta1{Fake: &c.Fake} diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index 020e785bf..c8f54596f 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -27,6 +27,7 @@ import ( gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1" gatewayv1 "github.com/fluxcd/flagger/pkg/apis/gloo/gateway/v1" gloov1 "github.com/fluxcd/flagger/pkg/apis/gloo/gloo/v1" + httpv1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" networkingv1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1" kedav1alpha1 "github.com/fluxcd/flagger/pkg/apis/keda/v1alpha1" kumav1alpha1 "github.com/fluxcd/flagger/pkg/apis/kuma/v1alpha1" @@ -54,6 +55,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ gatewayapiv1beta1.AddToScheme, gatewayapiv1.AddToScheme, gloov1.AddToScheme, + httpv1alpha1.AddToScheme, networkingv1beta1.AddToScheme, kedav1alpha1.AddToScheme, kumav1alpha1.AddToScheme, diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index 7f446ef79..26164ba7f 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -27,6 +27,7 @@ import ( gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1" gatewayv1 "github.com/fluxcd/flagger/pkg/apis/gloo/gateway/v1" gloov1 "github.com/fluxcd/flagger/pkg/apis/gloo/gloo/v1" + httpv1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" networkingv1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1" kedav1alpha1 "github.com/fluxcd/flagger/pkg/apis/keda/v1alpha1" kumav1alpha1 "github.com/fluxcd/flagger/pkg/apis/kuma/v1alpha1" @@ -54,6 +55,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ gatewayapiv1beta1.AddToScheme, gatewayapiv1.AddToScheme, gloov1.AddToScheme, + httpv1alpha1.AddToScheme, networkingv1beta1.AddToScheme, kedav1alpha1.AddToScheme, kumav1alpha1.AddToScheme, diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/clusterhttpscalingset.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/clusterhttpscalingset.go new file mode 100644 index 000000000..de350b98f --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/clusterhttpscalingset.go @@ -0,0 +1,195 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + scheme "github.com/fluxcd/flagger/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ClusterHTTPScalingSetsGetter has a method to return a ClusterHTTPScalingSetInterface. +// A group's client should implement this interface. +type ClusterHTTPScalingSetsGetter interface { + ClusterHTTPScalingSets(namespace string) ClusterHTTPScalingSetInterface +} + +// ClusterHTTPScalingSetInterface has methods to work with ClusterHTTPScalingSet resources. +type ClusterHTTPScalingSetInterface interface { + Create(ctx context.Context, clusterHTTPScalingSet *v1alpha1.ClusterHTTPScalingSet, opts v1.CreateOptions) (*v1alpha1.ClusterHTTPScalingSet, error) + Update(ctx context.Context, clusterHTTPScalingSet *v1alpha1.ClusterHTTPScalingSet, opts v1.UpdateOptions) (*v1alpha1.ClusterHTTPScalingSet, error) + UpdateStatus(ctx context.Context, clusterHTTPScalingSet *v1alpha1.ClusterHTTPScalingSet, opts v1.UpdateOptions) (*v1alpha1.ClusterHTTPScalingSet, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ClusterHTTPScalingSet, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ClusterHTTPScalingSetList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterHTTPScalingSet, err error) + ClusterHTTPScalingSetExpansion +} + +// clusterHTTPScalingSets implements ClusterHTTPScalingSetInterface +type clusterHTTPScalingSets struct { + client rest.Interface + ns string +} + +// newClusterHTTPScalingSets returns a ClusterHTTPScalingSets +func newClusterHTTPScalingSets(c *HttpV1alpha1Client, namespace string) *clusterHTTPScalingSets { + return &clusterHTTPScalingSets{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the clusterHTTPScalingSet, and returns the corresponding clusterHTTPScalingSet object, and an error if there is any. +func (c *clusterHTTPScalingSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterHTTPScalingSet, err error) { + result = &v1alpha1.ClusterHTTPScalingSet{} + err = c.client.Get(). + Namespace(c.ns). + Resource("clusterhttpscalingsets"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ClusterHTTPScalingSets that match those selectors. +func (c *clusterHTTPScalingSets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterHTTPScalingSetList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ClusterHTTPScalingSetList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("clusterhttpscalingsets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested clusterHTTPScalingSets. +func (c *clusterHTTPScalingSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("clusterhttpscalingsets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a clusterHTTPScalingSet and creates it. Returns the server's representation of the clusterHTTPScalingSet, and an error, if there is any. +func (c *clusterHTTPScalingSets) Create(ctx context.Context, clusterHTTPScalingSet *v1alpha1.ClusterHTTPScalingSet, opts v1.CreateOptions) (result *v1alpha1.ClusterHTTPScalingSet, err error) { + result = &v1alpha1.ClusterHTTPScalingSet{} + err = c.client.Post(). + Namespace(c.ns). + Resource("clusterhttpscalingsets"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(clusterHTTPScalingSet). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a clusterHTTPScalingSet and updates it. Returns the server's representation of the clusterHTTPScalingSet, and an error, if there is any. +func (c *clusterHTTPScalingSets) Update(ctx context.Context, clusterHTTPScalingSet *v1alpha1.ClusterHTTPScalingSet, opts v1.UpdateOptions) (result *v1alpha1.ClusterHTTPScalingSet, err error) { + result = &v1alpha1.ClusterHTTPScalingSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("clusterhttpscalingsets"). + Name(clusterHTTPScalingSet.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(clusterHTTPScalingSet). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *clusterHTTPScalingSets) UpdateStatus(ctx context.Context, clusterHTTPScalingSet *v1alpha1.ClusterHTTPScalingSet, opts v1.UpdateOptions) (result *v1alpha1.ClusterHTTPScalingSet, err error) { + result = &v1alpha1.ClusterHTTPScalingSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("clusterhttpscalingsets"). + Name(clusterHTTPScalingSet.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(clusterHTTPScalingSet). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the clusterHTTPScalingSet and deletes it. Returns an error if one occurs. +func (c *clusterHTTPScalingSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("clusterhttpscalingsets"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *clusterHTTPScalingSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("clusterhttpscalingsets"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched clusterHTTPScalingSet. +func (c *clusterHTTPScalingSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterHTTPScalingSet, err error) { + result = &v1alpha1.ClusterHTTPScalingSet{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("clusterhttpscalingsets"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/doc.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/doc.go new file mode 100644 index 000000000..9c7b8cc3b --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/doc.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/doc.go new file mode 100644 index 000000000..1ccd91197 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_clusterhttpscalingset.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_clusterhttpscalingset.go new file mode 100644 index 000000000..7c8dffdb2 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_clusterhttpscalingset.go @@ -0,0 +1,141 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeClusterHTTPScalingSets implements ClusterHTTPScalingSetInterface +type FakeClusterHTTPScalingSets struct { + Fake *FakeHttpV1alpha1 + ns string +} + +var clusterhttpscalingsetsResource = v1alpha1.SchemeGroupVersion.WithResource("clusterhttpscalingsets") + +var clusterhttpscalingsetsKind = v1alpha1.SchemeGroupVersion.WithKind("ClusterHTTPScalingSet") + +// Get takes name of the clusterHTTPScalingSet, and returns the corresponding clusterHTTPScalingSet object, and an error if there is any. +func (c *FakeClusterHTTPScalingSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterHTTPScalingSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(clusterhttpscalingsetsResource, c.ns, name), &v1alpha1.ClusterHTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ClusterHTTPScalingSet), err +} + +// List takes label and field selectors, and returns the list of ClusterHTTPScalingSets that match those selectors. +func (c *FakeClusterHTTPScalingSets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterHTTPScalingSetList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(clusterhttpscalingsetsResource, clusterhttpscalingsetsKind, c.ns, opts), &v1alpha1.ClusterHTTPScalingSetList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ClusterHTTPScalingSetList{ListMeta: obj.(*v1alpha1.ClusterHTTPScalingSetList).ListMeta} + for _, item := range obj.(*v1alpha1.ClusterHTTPScalingSetList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested clusterHTTPScalingSets. +func (c *FakeClusterHTTPScalingSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(clusterhttpscalingsetsResource, c.ns, opts)) + +} + +// Create takes the representation of a clusterHTTPScalingSet and creates it. Returns the server's representation of the clusterHTTPScalingSet, and an error, if there is any. +func (c *FakeClusterHTTPScalingSets) Create(ctx context.Context, clusterHTTPScalingSet *v1alpha1.ClusterHTTPScalingSet, opts v1.CreateOptions) (result *v1alpha1.ClusterHTTPScalingSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(clusterhttpscalingsetsResource, c.ns, clusterHTTPScalingSet), &v1alpha1.ClusterHTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ClusterHTTPScalingSet), err +} + +// Update takes the representation of a clusterHTTPScalingSet and updates it. Returns the server's representation of the clusterHTTPScalingSet, and an error, if there is any. +func (c *FakeClusterHTTPScalingSets) Update(ctx context.Context, clusterHTTPScalingSet *v1alpha1.ClusterHTTPScalingSet, opts v1.UpdateOptions) (result *v1alpha1.ClusterHTTPScalingSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(clusterhttpscalingsetsResource, c.ns, clusterHTTPScalingSet), &v1alpha1.ClusterHTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ClusterHTTPScalingSet), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeClusterHTTPScalingSets) UpdateStatus(ctx context.Context, clusterHTTPScalingSet *v1alpha1.ClusterHTTPScalingSet, opts v1.UpdateOptions) (*v1alpha1.ClusterHTTPScalingSet, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(clusterhttpscalingsetsResource, "status", c.ns, clusterHTTPScalingSet), &v1alpha1.ClusterHTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ClusterHTTPScalingSet), err +} + +// Delete takes name of the clusterHTTPScalingSet and deletes it. Returns an error if one occurs. +func (c *FakeClusterHTTPScalingSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(clusterhttpscalingsetsResource, c.ns, name, opts), &v1alpha1.ClusterHTTPScalingSet{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeClusterHTTPScalingSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(clusterhttpscalingsetsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ClusterHTTPScalingSetList{}) + return err +} + +// Patch applies the patch and returns the patched clusterHTTPScalingSet. +func (c *FakeClusterHTTPScalingSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterHTTPScalingSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(clusterhttpscalingsetsResource, c.ns, name, pt, data, subresources...), &v1alpha1.ClusterHTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ClusterHTTPScalingSet), err +} diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_http_client.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_http_client.go new file mode 100644 index 000000000..b495666c6 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_http_client.go @@ -0,0 +1,48 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/http/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeHttpV1alpha1 struct { + *testing.Fake +} + +func (c *FakeHttpV1alpha1) ClusterHTTPScalingSets(namespace string) v1alpha1.ClusterHTTPScalingSetInterface { + return &FakeClusterHTTPScalingSets{c, namespace} +} + +func (c *FakeHttpV1alpha1) HTTPScaledObjects(namespace string) v1alpha1.HTTPScaledObjectInterface { + return &FakeHTTPScaledObjects{c, namespace} +} + +func (c *FakeHttpV1alpha1) HTTPScalingSets(namespace string) v1alpha1.HTTPScalingSetInterface { + return &FakeHTTPScalingSets{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeHttpV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_httpscaledobject.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_httpscaledobject.go new file mode 100644 index 000000000..a36f62af8 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_httpscaledobject.go @@ -0,0 +1,141 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeHTTPScaledObjects implements HTTPScaledObjectInterface +type FakeHTTPScaledObjects struct { + Fake *FakeHttpV1alpha1 + ns string +} + +var httpscaledobjectsResource = v1alpha1.SchemeGroupVersion.WithResource("httpscaledobjects") + +var httpscaledobjectsKind = v1alpha1.SchemeGroupVersion.WithKind("HTTPScaledObject") + +// Get takes name of the hTTPScaledObject, and returns the corresponding hTTPScaledObject object, and an error if there is any. +func (c *FakeHTTPScaledObjects) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.HTTPScaledObject, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(httpscaledobjectsResource, c.ns, name), &v1alpha1.HTTPScaledObject{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScaledObject), err +} + +// List takes label and field selectors, and returns the list of HTTPScaledObjects that match those selectors. +func (c *FakeHTTPScaledObjects) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.HTTPScaledObjectList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(httpscaledobjectsResource, httpscaledobjectsKind, c.ns, opts), &v1alpha1.HTTPScaledObjectList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.HTTPScaledObjectList{ListMeta: obj.(*v1alpha1.HTTPScaledObjectList).ListMeta} + for _, item := range obj.(*v1alpha1.HTTPScaledObjectList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested hTTPScaledObjects. +func (c *FakeHTTPScaledObjects) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(httpscaledobjectsResource, c.ns, opts)) + +} + +// Create takes the representation of a hTTPScaledObject and creates it. Returns the server's representation of the hTTPScaledObject, and an error, if there is any. +func (c *FakeHTTPScaledObjects) Create(ctx context.Context, hTTPScaledObject *v1alpha1.HTTPScaledObject, opts v1.CreateOptions) (result *v1alpha1.HTTPScaledObject, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(httpscaledobjectsResource, c.ns, hTTPScaledObject), &v1alpha1.HTTPScaledObject{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScaledObject), err +} + +// Update takes the representation of a hTTPScaledObject and updates it. Returns the server's representation of the hTTPScaledObject, and an error, if there is any. +func (c *FakeHTTPScaledObjects) Update(ctx context.Context, hTTPScaledObject *v1alpha1.HTTPScaledObject, opts v1.UpdateOptions) (result *v1alpha1.HTTPScaledObject, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(httpscaledobjectsResource, c.ns, hTTPScaledObject), &v1alpha1.HTTPScaledObject{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScaledObject), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeHTTPScaledObjects) UpdateStatus(ctx context.Context, hTTPScaledObject *v1alpha1.HTTPScaledObject, opts v1.UpdateOptions) (*v1alpha1.HTTPScaledObject, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(httpscaledobjectsResource, "status", c.ns, hTTPScaledObject), &v1alpha1.HTTPScaledObject{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScaledObject), err +} + +// Delete takes name of the hTTPScaledObject and deletes it. Returns an error if one occurs. +func (c *FakeHTTPScaledObjects) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(httpscaledobjectsResource, c.ns, name, opts), &v1alpha1.HTTPScaledObject{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeHTTPScaledObjects) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(httpscaledobjectsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.HTTPScaledObjectList{}) + return err +} + +// Patch applies the patch and returns the patched hTTPScaledObject. +func (c *FakeHTTPScaledObjects) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.HTTPScaledObject, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(httpscaledobjectsResource, c.ns, name, pt, data, subresources...), &v1alpha1.HTTPScaledObject{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScaledObject), err +} diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_httpscalingset.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_httpscalingset.go new file mode 100644 index 000000000..5d134df15 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/fake/fake_httpscalingset.go @@ -0,0 +1,141 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeHTTPScalingSets implements HTTPScalingSetInterface +type FakeHTTPScalingSets struct { + Fake *FakeHttpV1alpha1 + ns string +} + +var httpscalingsetsResource = v1alpha1.SchemeGroupVersion.WithResource("httpscalingsets") + +var httpscalingsetsKind = v1alpha1.SchemeGroupVersion.WithKind("HTTPScalingSet") + +// Get takes name of the hTTPScalingSet, and returns the corresponding hTTPScalingSet object, and an error if there is any. +func (c *FakeHTTPScalingSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.HTTPScalingSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(httpscalingsetsResource, c.ns, name), &v1alpha1.HTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScalingSet), err +} + +// List takes label and field selectors, and returns the list of HTTPScalingSets that match those selectors. +func (c *FakeHTTPScalingSets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.HTTPScalingSetList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(httpscalingsetsResource, httpscalingsetsKind, c.ns, opts), &v1alpha1.HTTPScalingSetList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.HTTPScalingSetList{ListMeta: obj.(*v1alpha1.HTTPScalingSetList).ListMeta} + for _, item := range obj.(*v1alpha1.HTTPScalingSetList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested hTTPScalingSets. +func (c *FakeHTTPScalingSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(httpscalingsetsResource, c.ns, opts)) + +} + +// Create takes the representation of a hTTPScalingSet and creates it. Returns the server's representation of the hTTPScalingSet, and an error, if there is any. +func (c *FakeHTTPScalingSets) Create(ctx context.Context, hTTPScalingSet *v1alpha1.HTTPScalingSet, opts v1.CreateOptions) (result *v1alpha1.HTTPScalingSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(httpscalingsetsResource, c.ns, hTTPScalingSet), &v1alpha1.HTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScalingSet), err +} + +// Update takes the representation of a hTTPScalingSet and updates it. Returns the server's representation of the hTTPScalingSet, and an error, if there is any. +func (c *FakeHTTPScalingSets) Update(ctx context.Context, hTTPScalingSet *v1alpha1.HTTPScalingSet, opts v1.UpdateOptions) (result *v1alpha1.HTTPScalingSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(httpscalingsetsResource, c.ns, hTTPScalingSet), &v1alpha1.HTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScalingSet), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeHTTPScalingSets) UpdateStatus(ctx context.Context, hTTPScalingSet *v1alpha1.HTTPScalingSet, opts v1.UpdateOptions) (*v1alpha1.HTTPScalingSet, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(httpscalingsetsResource, "status", c.ns, hTTPScalingSet), &v1alpha1.HTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScalingSet), err +} + +// Delete takes name of the hTTPScalingSet and deletes it. Returns an error if one occurs. +func (c *FakeHTTPScalingSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(httpscalingsetsResource, c.ns, name, opts), &v1alpha1.HTTPScalingSet{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeHTTPScalingSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(httpscalingsetsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.HTTPScalingSetList{}) + return err +} + +// Patch applies the patch and returns the patched hTTPScalingSet. +func (c *FakeHTTPScalingSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.HTTPScalingSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(httpscalingsetsResource, c.ns, name, pt, data, subresources...), &v1alpha1.HTTPScalingSet{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.HTTPScalingSet), err +} diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/generated_expansion.go new file mode 100644 index 000000000..2244fdafb --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/generated_expansion.go @@ -0,0 +1,25 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type ClusterHTTPScalingSetExpansion interface{} + +type HTTPScaledObjectExpansion interface{} + +type HTTPScalingSetExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/http_client.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/http_client.go new file mode 100644 index 000000000..39d27e87a --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/http_client.go @@ -0,0 +1,117 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "net/http" + + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + "github.com/fluxcd/flagger/pkg/client/clientset/versioned/scheme" + rest "k8s.io/client-go/rest" +) + +type HttpV1alpha1Interface interface { + RESTClient() rest.Interface + ClusterHTTPScalingSetsGetter + HTTPScaledObjectsGetter + HTTPScalingSetsGetter +} + +// HttpV1alpha1Client is used to interact with features provided by the http.keda.sh group. +type HttpV1alpha1Client struct { + restClient rest.Interface +} + +func (c *HttpV1alpha1Client) ClusterHTTPScalingSets(namespace string) ClusterHTTPScalingSetInterface { + return newClusterHTTPScalingSets(c, namespace) +} + +func (c *HttpV1alpha1Client) HTTPScaledObjects(namespace string) HTTPScaledObjectInterface { + return newHTTPScaledObjects(c, namespace) +} + +func (c *HttpV1alpha1Client) HTTPScalingSets(namespace string) HTTPScalingSetInterface { + return newHTTPScalingSets(c, namespace) +} + +// NewForConfig creates a new HttpV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*HttpV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new HttpV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*HttpV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &HttpV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new HttpV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *HttpV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new HttpV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *HttpV1alpha1Client { + return &HttpV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *HttpV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/httpscaledobject.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/httpscaledobject.go new file mode 100644 index 000000000..de0e6ab24 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/httpscaledobject.go @@ -0,0 +1,195 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + scheme "github.com/fluxcd/flagger/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// HTTPScaledObjectsGetter has a method to return a HTTPScaledObjectInterface. +// A group's client should implement this interface. +type HTTPScaledObjectsGetter interface { + HTTPScaledObjects(namespace string) HTTPScaledObjectInterface +} + +// HTTPScaledObjectInterface has methods to work with HTTPScaledObject resources. +type HTTPScaledObjectInterface interface { + Create(ctx context.Context, hTTPScaledObject *v1alpha1.HTTPScaledObject, opts v1.CreateOptions) (*v1alpha1.HTTPScaledObject, error) + Update(ctx context.Context, hTTPScaledObject *v1alpha1.HTTPScaledObject, opts v1.UpdateOptions) (*v1alpha1.HTTPScaledObject, error) + UpdateStatus(ctx context.Context, hTTPScaledObject *v1alpha1.HTTPScaledObject, opts v1.UpdateOptions) (*v1alpha1.HTTPScaledObject, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.HTTPScaledObject, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.HTTPScaledObjectList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.HTTPScaledObject, err error) + HTTPScaledObjectExpansion +} + +// hTTPScaledObjects implements HTTPScaledObjectInterface +type hTTPScaledObjects struct { + client rest.Interface + ns string +} + +// newHTTPScaledObjects returns a HTTPScaledObjects +func newHTTPScaledObjects(c *HttpV1alpha1Client, namespace string) *hTTPScaledObjects { + return &hTTPScaledObjects{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the hTTPScaledObject, and returns the corresponding hTTPScaledObject object, and an error if there is any. +func (c *hTTPScaledObjects) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.HTTPScaledObject, err error) { + result = &v1alpha1.HTTPScaledObject{} + err = c.client.Get(). + Namespace(c.ns). + Resource("httpscaledobjects"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of HTTPScaledObjects that match those selectors. +func (c *hTTPScaledObjects) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.HTTPScaledObjectList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.HTTPScaledObjectList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("httpscaledobjects"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested hTTPScaledObjects. +func (c *hTTPScaledObjects) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("httpscaledobjects"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a hTTPScaledObject and creates it. Returns the server's representation of the hTTPScaledObject, and an error, if there is any. +func (c *hTTPScaledObjects) Create(ctx context.Context, hTTPScaledObject *v1alpha1.HTTPScaledObject, opts v1.CreateOptions) (result *v1alpha1.HTTPScaledObject, err error) { + result = &v1alpha1.HTTPScaledObject{} + err = c.client.Post(). + Namespace(c.ns). + Resource("httpscaledobjects"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(hTTPScaledObject). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a hTTPScaledObject and updates it. Returns the server's representation of the hTTPScaledObject, and an error, if there is any. +func (c *hTTPScaledObjects) Update(ctx context.Context, hTTPScaledObject *v1alpha1.HTTPScaledObject, opts v1.UpdateOptions) (result *v1alpha1.HTTPScaledObject, err error) { + result = &v1alpha1.HTTPScaledObject{} + err = c.client.Put(). + Namespace(c.ns). + Resource("httpscaledobjects"). + Name(hTTPScaledObject.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(hTTPScaledObject). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *hTTPScaledObjects) UpdateStatus(ctx context.Context, hTTPScaledObject *v1alpha1.HTTPScaledObject, opts v1.UpdateOptions) (result *v1alpha1.HTTPScaledObject, err error) { + result = &v1alpha1.HTTPScaledObject{} + err = c.client.Put(). + Namespace(c.ns). + Resource("httpscaledobjects"). + Name(hTTPScaledObject.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(hTTPScaledObject). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the hTTPScaledObject and deletes it. Returns an error if one occurs. +func (c *hTTPScaledObjects) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("httpscaledobjects"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *hTTPScaledObjects) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("httpscaledobjects"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched hTTPScaledObject. +func (c *hTTPScaledObjects) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.HTTPScaledObject, err error) { + result = &v1alpha1.HTTPScaledObject{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("httpscaledobjects"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/http/v1alpha1/httpscalingset.go b/pkg/client/clientset/versioned/typed/http/v1alpha1/httpscalingset.go new file mode 100644 index 000000000..3c594c949 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/http/v1alpha1/httpscalingset.go @@ -0,0 +1,195 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + scheme "github.com/fluxcd/flagger/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// HTTPScalingSetsGetter has a method to return a HTTPScalingSetInterface. +// A group's client should implement this interface. +type HTTPScalingSetsGetter interface { + HTTPScalingSets(namespace string) HTTPScalingSetInterface +} + +// HTTPScalingSetInterface has methods to work with HTTPScalingSet resources. +type HTTPScalingSetInterface interface { + Create(ctx context.Context, hTTPScalingSet *v1alpha1.HTTPScalingSet, opts v1.CreateOptions) (*v1alpha1.HTTPScalingSet, error) + Update(ctx context.Context, hTTPScalingSet *v1alpha1.HTTPScalingSet, opts v1.UpdateOptions) (*v1alpha1.HTTPScalingSet, error) + UpdateStatus(ctx context.Context, hTTPScalingSet *v1alpha1.HTTPScalingSet, opts v1.UpdateOptions) (*v1alpha1.HTTPScalingSet, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.HTTPScalingSet, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.HTTPScalingSetList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.HTTPScalingSet, err error) + HTTPScalingSetExpansion +} + +// hTTPScalingSets implements HTTPScalingSetInterface +type hTTPScalingSets struct { + client rest.Interface + ns string +} + +// newHTTPScalingSets returns a HTTPScalingSets +func newHTTPScalingSets(c *HttpV1alpha1Client, namespace string) *hTTPScalingSets { + return &hTTPScalingSets{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the hTTPScalingSet, and returns the corresponding hTTPScalingSet object, and an error if there is any. +func (c *hTTPScalingSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.HTTPScalingSet, err error) { + result = &v1alpha1.HTTPScalingSet{} + err = c.client.Get(). + Namespace(c.ns). + Resource("httpscalingsets"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of HTTPScalingSets that match those selectors. +func (c *hTTPScalingSets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.HTTPScalingSetList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.HTTPScalingSetList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("httpscalingsets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested hTTPScalingSets. +func (c *hTTPScalingSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("httpscalingsets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a hTTPScalingSet and creates it. Returns the server's representation of the hTTPScalingSet, and an error, if there is any. +func (c *hTTPScalingSets) Create(ctx context.Context, hTTPScalingSet *v1alpha1.HTTPScalingSet, opts v1.CreateOptions) (result *v1alpha1.HTTPScalingSet, err error) { + result = &v1alpha1.HTTPScalingSet{} + err = c.client.Post(). + Namespace(c.ns). + Resource("httpscalingsets"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(hTTPScalingSet). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a hTTPScalingSet and updates it. Returns the server's representation of the hTTPScalingSet, and an error, if there is any. +func (c *hTTPScalingSets) Update(ctx context.Context, hTTPScalingSet *v1alpha1.HTTPScalingSet, opts v1.UpdateOptions) (result *v1alpha1.HTTPScalingSet, err error) { + result = &v1alpha1.HTTPScalingSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("httpscalingsets"). + Name(hTTPScalingSet.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(hTTPScalingSet). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *hTTPScalingSets) UpdateStatus(ctx context.Context, hTTPScalingSet *v1alpha1.HTTPScalingSet, opts v1.UpdateOptions) (result *v1alpha1.HTTPScalingSet, err error) { + result = &v1alpha1.HTTPScalingSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("httpscalingsets"). + Name(hTTPScalingSet.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(hTTPScalingSet). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the hTTPScalingSet and deletes it. Returns an error if one occurs. +func (c *hTTPScalingSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("httpscalingsets"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *hTTPScalingSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("httpscalingsets"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched hTTPScalingSet. +func (c *hTTPScalingSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.HTTPScalingSet, err error) { + result = &v1alpha1.HTTPScalingSet{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("httpscalingsets"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 66f1e2369..c962779b9 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -30,6 +30,7 @@ import ( gateway "github.com/fluxcd/flagger/pkg/client/informers/externalversions/gateway" gatewayapi "github.com/fluxcd/flagger/pkg/client/informers/externalversions/gatewayapi" gloo "github.com/fluxcd/flagger/pkg/client/informers/externalversions/gloo" + http "github.com/fluxcd/flagger/pkg/client/informers/externalversions/http" internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces" istio "github.com/fluxcd/flagger/pkg/client/informers/externalversions/istio" keda "github.com/fluxcd/flagger/pkg/client/informers/externalversions/keda" @@ -260,6 +261,7 @@ type SharedInformerFactory interface { Gateway() gateway.Interface Gatewayapi() gatewayapi.Interface Gloo() gloo.Interface + Http() http.Interface Networking() istio.Interface Keda() keda.Interface Kuma() kuma.Interface @@ -292,6 +294,10 @@ func (f *sharedInformerFactory) Gloo() gloo.Interface { return gloo.New(f, f.namespace, f.tweakListOptions) } +func (f *sharedInformerFactory) Http() http.Interface { + return http.New(f, f.namespace, f.tweakListOptions) +} + func (f *sharedInformerFactory) Networking() istio.Interface { return istio.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 0158715f3..9fc021209 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -29,8 +29,9 @@ import ( gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1" v1 "github.com/fluxcd/flagger/pkg/apis/gloo/gateway/v1" gloov1 "github.com/fluxcd/flagger/pkg/apis/gloo/gloo/v1" + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1" - v1alpha1 "github.com/fluxcd/flagger/pkg/apis/keda/v1alpha1" + kedav1alpha1 "github.com/fluxcd/flagger/pkg/apis/keda/v1alpha1" kumav1alpha1 "github.com/fluxcd/flagger/pkg/apis/kuma/v1alpha1" projectcontourv1 "github.com/fluxcd/flagger/pkg/apis/projectcontour/v1" smiv1alpha1 "github.com/fluxcd/flagger/pkg/apis/smi/v1alpha1" @@ -111,8 +112,16 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case gloov1.SchemeGroupVersion.WithResource("upstreams"): return &genericInformer{resource: resource.GroupResource(), informer: f.Gloo().V1().Upstreams().Informer()}, nil + // Group=http.keda.sh, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("clusterhttpscalingsets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Http().V1alpha1().ClusterHTTPScalingSets().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("httpscaledobjects"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Http().V1alpha1().HTTPScaledObjects().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("httpscalingsets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Http().V1alpha1().HTTPScalingSets().Informer()}, nil + // Group=keda.sh, Version=v1alpha1 - case v1alpha1.SchemeGroupVersion.WithResource("scaledobjects"): + case kedav1alpha1.SchemeGroupVersion.WithResource("scaledobjects"): return &genericInformer{resource: resource.GroupResource(), informer: f.Keda().V1alpha1().ScaledObjects().Informer()}, nil // Group=kuma.io, Version=v1alpha1 diff --git a/pkg/client/informers/externalversions/http/interface.go b/pkg/client/informers/externalversions/http/interface.go new file mode 100644 index 000000000..ea0cf4502 --- /dev/null +++ b/pkg/client/informers/externalversions/http/interface.go @@ -0,0 +1,46 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package http + +import ( + v1alpha1 "github.com/fluxcd/flagger/pkg/client/informers/externalversions/http/v1alpha1" + internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/client/informers/externalversions/http/v1alpha1/clusterhttpscalingset.go b/pkg/client/informers/externalversions/http/v1alpha1/clusterhttpscalingset.go new file mode 100644 index 000000000..10545cf3e --- /dev/null +++ b/pkg/client/informers/externalversions/http/v1alpha1/clusterhttpscalingset.go @@ -0,0 +1,90 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + httpv1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + versioned "github.com/fluxcd/flagger/pkg/client/clientset/versioned" + internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/fluxcd/flagger/pkg/client/listers/http/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ClusterHTTPScalingSetInformer provides access to a shared informer and lister for +// ClusterHTTPScalingSets. +type ClusterHTTPScalingSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ClusterHTTPScalingSetLister +} + +type clusterHTTPScalingSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewClusterHTTPScalingSetInformer constructs a new informer for ClusterHTTPScalingSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewClusterHTTPScalingSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredClusterHTTPScalingSetInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredClusterHTTPScalingSetInformer constructs a new informer for ClusterHTTPScalingSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredClusterHTTPScalingSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.HttpV1alpha1().ClusterHTTPScalingSets(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.HttpV1alpha1().ClusterHTTPScalingSets(namespace).Watch(context.TODO(), options) + }, + }, + &httpv1alpha1.ClusterHTTPScalingSet{}, + resyncPeriod, + indexers, + ) +} + +func (f *clusterHTTPScalingSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredClusterHTTPScalingSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *clusterHTTPScalingSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&httpv1alpha1.ClusterHTTPScalingSet{}, f.defaultInformer) +} + +func (f *clusterHTTPScalingSetInformer) Lister() v1alpha1.ClusterHTTPScalingSetLister { + return v1alpha1.NewClusterHTTPScalingSetLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/http/v1alpha1/httpscaledobject.go b/pkg/client/informers/externalversions/http/v1alpha1/httpscaledobject.go new file mode 100644 index 000000000..ecc194c9f --- /dev/null +++ b/pkg/client/informers/externalversions/http/v1alpha1/httpscaledobject.go @@ -0,0 +1,90 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + httpv1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + versioned "github.com/fluxcd/flagger/pkg/client/clientset/versioned" + internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/fluxcd/flagger/pkg/client/listers/http/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// HTTPScaledObjectInformer provides access to a shared informer and lister for +// HTTPScaledObjects. +type HTTPScaledObjectInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.HTTPScaledObjectLister +} + +type hTTPScaledObjectInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewHTTPScaledObjectInformer constructs a new informer for HTTPScaledObject type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewHTTPScaledObjectInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredHTTPScaledObjectInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredHTTPScaledObjectInformer constructs a new informer for HTTPScaledObject type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredHTTPScaledObjectInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.HttpV1alpha1().HTTPScaledObjects(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.HttpV1alpha1().HTTPScaledObjects(namespace).Watch(context.TODO(), options) + }, + }, + &httpv1alpha1.HTTPScaledObject{}, + resyncPeriod, + indexers, + ) +} + +func (f *hTTPScaledObjectInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredHTTPScaledObjectInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *hTTPScaledObjectInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&httpv1alpha1.HTTPScaledObject{}, f.defaultInformer) +} + +func (f *hTTPScaledObjectInformer) Lister() v1alpha1.HTTPScaledObjectLister { + return v1alpha1.NewHTTPScaledObjectLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/http/v1alpha1/httpscalingset.go b/pkg/client/informers/externalversions/http/v1alpha1/httpscalingset.go new file mode 100644 index 000000000..8a7f62226 --- /dev/null +++ b/pkg/client/informers/externalversions/http/v1alpha1/httpscalingset.go @@ -0,0 +1,90 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + httpv1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + versioned "github.com/fluxcd/flagger/pkg/client/clientset/versioned" + internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/fluxcd/flagger/pkg/client/listers/http/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// HTTPScalingSetInformer provides access to a shared informer and lister for +// HTTPScalingSets. +type HTTPScalingSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.HTTPScalingSetLister +} + +type hTTPScalingSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewHTTPScalingSetInformer constructs a new informer for HTTPScalingSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewHTTPScalingSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredHTTPScalingSetInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredHTTPScalingSetInformer constructs a new informer for HTTPScalingSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredHTTPScalingSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.HttpV1alpha1().HTTPScalingSets(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.HttpV1alpha1().HTTPScalingSets(namespace).Watch(context.TODO(), options) + }, + }, + &httpv1alpha1.HTTPScalingSet{}, + resyncPeriod, + indexers, + ) +} + +func (f *hTTPScalingSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredHTTPScalingSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *hTTPScalingSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&httpv1alpha1.HTTPScalingSet{}, f.defaultInformer) +} + +func (f *hTTPScalingSetInformer) Lister() v1alpha1.HTTPScalingSetLister { + return v1alpha1.NewHTTPScalingSetLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/http/v1alpha1/interface.go b/pkg/client/informers/externalversions/http/v1alpha1/interface.go new file mode 100644 index 000000000..8423c6fdb --- /dev/null +++ b/pkg/client/informers/externalversions/http/v1alpha1/interface.go @@ -0,0 +1,59 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ClusterHTTPScalingSets returns a ClusterHTTPScalingSetInformer. + ClusterHTTPScalingSets() ClusterHTTPScalingSetInformer + // HTTPScaledObjects returns a HTTPScaledObjectInformer. + HTTPScaledObjects() HTTPScaledObjectInformer + // HTTPScalingSets returns a HTTPScalingSetInformer. + HTTPScalingSets() HTTPScalingSetInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// ClusterHTTPScalingSets returns a ClusterHTTPScalingSetInformer. +func (v *version) ClusterHTTPScalingSets() ClusterHTTPScalingSetInformer { + return &clusterHTTPScalingSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// HTTPScaledObjects returns a HTTPScaledObjectInformer. +func (v *version) HTTPScaledObjects() HTTPScaledObjectInformer { + return &hTTPScaledObjectInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// HTTPScalingSets returns a HTTPScalingSetInformer. +func (v *version) HTTPScalingSets() HTTPScalingSetInformer { + return &hTTPScalingSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/listers/http/v1alpha1/clusterhttpscalingset.go b/pkg/client/listers/http/v1alpha1/clusterhttpscalingset.go new file mode 100644 index 000000000..5eab21c98 --- /dev/null +++ b/pkg/client/listers/http/v1alpha1/clusterhttpscalingset.go @@ -0,0 +1,99 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ClusterHTTPScalingSetLister helps list ClusterHTTPScalingSets. +// All objects returned here must be treated as read-only. +type ClusterHTTPScalingSetLister interface { + // List lists all ClusterHTTPScalingSets in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ClusterHTTPScalingSet, err error) + // ClusterHTTPScalingSets returns an object that can list and get ClusterHTTPScalingSets. + ClusterHTTPScalingSets(namespace string) ClusterHTTPScalingSetNamespaceLister + ClusterHTTPScalingSetListerExpansion +} + +// clusterHTTPScalingSetLister implements the ClusterHTTPScalingSetLister interface. +type clusterHTTPScalingSetLister struct { + indexer cache.Indexer +} + +// NewClusterHTTPScalingSetLister returns a new ClusterHTTPScalingSetLister. +func NewClusterHTTPScalingSetLister(indexer cache.Indexer) ClusterHTTPScalingSetLister { + return &clusterHTTPScalingSetLister{indexer: indexer} +} + +// List lists all ClusterHTTPScalingSets in the indexer. +func (s *clusterHTTPScalingSetLister) List(selector labels.Selector) (ret []*v1alpha1.ClusterHTTPScalingSet, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ClusterHTTPScalingSet)) + }) + return ret, err +} + +// ClusterHTTPScalingSets returns an object that can list and get ClusterHTTPScalingSets. +func (s *clusterHTTPScalingSetLister) ClusterHTTPScalingSets(namespace string) ClusterHTTPScalingSetNamespaceLister { + return clusterHTTPScalingSetNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ClusterHTTPScalingSetNamespaceLister helps list and get ClusterHTTPScalingSets. +// All objects returned here must be treated as read-only. +type ClusterHTTPScalingSetNamespaceLister interface { + // List lists all ClusterHTTPScalingSets in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ClusterHTTPScalingSet, err error) + // Get retrieves the ClusterHTTPScalingSet from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ClusterHTTPScalingSet, error) + ClusterHTTPScalingSetNamespaceListerExpansion +} + +// clusterHTTPScalingSetNamespaceLister implements the ClusterHTTPScalingSetNamespaceLister +// interface. +type clusterHTTPScalingSetNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ClusterHTTPScalingSets in the indexer for a given namespace. +func (s clusterHTTPScalingSetNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ClusterHTTPScalingSet, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ClusterHTTPScalingSet)) + }) + return ret, err +} + +// Get retrieves the ClusterHTTPScalingSet from the indexer for a given namespace and name. +func (s clusterHTTPScalingSetNamespaceLister) Get(name string) (*v1alpha1.ClusterHTTPScalingSet, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("clusterhttpscalingset"), name) + } + return obj.(*v1alpha1.ClusterHTTPScalingSet), nil +} diff --git a/pkg/client/listers/http/v1alpha1/expansion_generated.go b/pkg/client/listers/http/v1alpha1/expansion_generated.go new file mode 100644 index 000000000..ba2ad2485 --- /dev/null +++ b/pkg/client/listers/http/v1alpha1/expansion_generated.go @@ -0,0 +1,43 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// ClusterHTTPScalingSetListerExpansion allows custom methods to be added to +// ClusterHTTPScalingSetLister. +type ClusterHTTPScalingSetListerExpansion interface{} + +// ClusterHTTPScalingSetNamespaceListerExpansion allows custom methods to be added to +// ClusterHTTPScalingSetNamespaceLister. +type ClusterHTTPScalingSetNamespaceListerExpansion interface{} + +// HTTPScaledObjectListerExpansion allows custom methods to be added to +// HTTPScaledObjectLister. +type HTTPScaledObjectListerExpansion interface{} + +// HTTPScaledObjectNamespaceListerExpansion allows custom methods to be added to +// HTTPScaledObjectNamespaceLister. +type HTTPScaledObjectNamespaceListerExpansion interface{} + +// HTTPScalingSetListerExpansion allows custom methods to be added to +// HTTPScalingSetLister. +type HTTPScalingSetListerExpansion interface{} + +// HTTPScalingSetNamespaceListerExpansion allows custom methods to be added to +// HTTPScalingSetNamespaceLister. +type HTTPScalingSetNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/http/v1alpha1/httpscaledobject.go b/pkg/client/listers/http/v1alpha1/httpscaledobject.go new file mode 100644 index 000000000..6a9c8df65 --- /dev/null +++ b/pkg/client/listers/http/v1alpha1/httpscaledobject.go @@ -0,0 +1,99 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// HTTPScaledObjectLister helps list HTTPScaledObjects. +// All objects returned here must be treated as read-only. +type HTTPScaledObjectLister interface { + // List lists all HTTPScaledObjects in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.HTTPScaledObject, err error) + // HTTPScaledObjects returns an object that can list and get HTTPScaledObjects. + HTTPScaledObjects(namespace string) HTTPScaledObjectNamespaceLister + HTTPScaledObjectListerExpansion +} + +// hTTPScaledObjectLister implements the HTTPScaledObjectLister interface. +type hTTPScaledObjectLister struct { + indexer cache.Indexer +} + +// NewHTTPScaledObjectLister returns a new HTTPScaledObjectLister. +func NewHTTPScaledObjectLister(indexer cache.Indexer) HTTPScaledObjectLister { + return &hTTPScaledObjectLister{indexer: indexer} +} + +// List lists all HTTPScaledObjects in the indexer. +func (s *hTTPScaledObjectLister) List(selector labels.Selector) (ret []*v1alpha1.HTTPScaledObject, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.HTTPScaledObject)) + }) + return ret, err +} + +// HTTPScaledObjects returns an object that can list and get HTTPScaledObjects. +func (s *hTTPScaledObjectLister) HTTPScaledObjects(namespace string) HTTPScaledObjectNamespaceLister { + return hTTPScaledObjectNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// HTTPScaledObjectNamespaceLister helps list and get HTTPScaledObjects. +// All objects returned here must be treated as read-only. +type HTTPScaledObjectNamespaceLister interface { + // List lists all HTTPScaledObjects in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.HTTPScaledObject, err error) + // Get retrieves the HTTPScaledObject from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.HTTPScaledObject, error) + HTTPScaledObjectNamespaceListerExpansion +} + +// hTTPScaledObjectNamespaceLister implements the HTTPScaledObjectNamespaceLister +// interface. +type hTTPScaledObjectNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all HTTPScaledObjects in the indexer for a given namespace. +func (s hTTPScaledObjectNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.HTTPScaledObject, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.HTTPScaledObject)) + }) + return ret, err +} + +// Get retrieves the HTTPScaledObject from the indexer for a given namespace and name. +func (s hTTPScaledObjectNamespaceLister) Get(name string) (*v1alpha1.HTTPScaledObject, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("httpscaledobject"), name) + } + return obj.(*v1alpha1.HTTPScaledObject), nil +} diff --git a/pkg/client/listers/http/v1alpha1/httpscalingset.go b/pkg/client/listers/http/v1alpha1/httpscalingset.go new file mode 100644 index 000000000..2fd70d4a2 --- /dev/null +++ b/pkg/client/listers/http/v1alpha1/httpscalingset.go @@ -0,0 +1,99 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/fluxcd/flagger/pkg/apis/http/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// HTTPScalingSetLister helps list HTTPScalingSets. +// All objects returned here must be treated as read-only. +type HTTPScalingSetLister interface { + // List lists all HTTPScalingSets in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.HTTPScalingSet, err error) + // HTTPScalingSets returns an object that can list and get HTTPScalingSets. + HTTPScalingSets(namespace string) HTTPScalingSetNamespaceLister + HTTPScalingSetListerExpansion +} + +// hTTPScalingSetLister implements the HTTPScalingSetLister interface. +type hTTPScalingSetLister struct { + indexer cache.Indexer +} + +// NewHTTPScalingSetLister returns a new HTTPScalingSetLister. +func NewHTTPScalingSetLister(indexer cache.Indexer) HTTPScalingSetLister { + return &hTTPScalingSetLister{indexer: indexer} +} + +// List lists all HTTPScalingSets in the indexer. +func (s *hTTPScalingSetLister) List(selector labels.Selector) (ret []*v1alpha1.HTTPScalingSet, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.HTTPScalingSet)) + }) + return ret, err +} + +// HTTPScalingSets returns an object that can list and get HTTPScalingSets. +func (s *hTTPScalingSetLister) HTTPScalingSets(namespace string) HTTPScalingSetNamespaceLister { + return hTTPScalingSetNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// HTTPScalingSetNamespaceLister helps list and get HTTPScalingSets. +// All objects returned here must be treated as read-only. +type HTTPScalingSetNamespaceLister interface { + // List lists all HTTPScalingSets in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.HTTPScalingSet, err error) + // Get retrieves the HTTPScalingSet from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.HTTPScalingSet, error) + HTTPScalingSetNamespaceListerExpansion +} + +// hTTPScalingSetNamespaceLister implements the HTTPScalingSetNamespaceLister +// interface. +type hTTPScalingSetNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all HTTPScalingSets in the indexer for a given namespace. +func (s hTTPScalingSetNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.HTTPScalingSet, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.HTTPScalingSet)) + }) + return ret, err +} + +// Get retrieves the HTTPScalingSet from the indexer for a given namespace and name. +func (s hTTPScalingSetNamespaceLister) Get(name string) (*v1alpha1.HTTPScalingSet, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("httpscalingset"), name) + } + return obj.(*v1alpha1.HTTPScalingSet), nil +} diff --git a/pkg/router/factory.go b/pkg/router/factory.go index 0a62a5ef0..ab380bf86 100644 --- a/pkg/router/factory.go +++ b/pkg/router/factory.go @@ -59,18 +59,16 @@ func NewFactory(kubeConfig *restclient.Config, kubeClient kubernetes.Interface, // KubernetesRouter returns a KubernetesRouter interface implementation func (factory *Factory) KubernetesRouter(kind string, labelSelector string, labelValue string, ports map[string]int32) KubernetesRouter { - switch kind { - case "Service": + if kind == "Service" { return &KubernetesNoopRouter{} - default: // Daemonset or Deployment - return &KubernetesDefaultRouter{ - logger: factory.logger, - flaggerClient: factory.flaggerClient, - kubeClient: factory.kubeClient, - labelSelector: labelSelector, - labelValue: labelValue, - ports: ports, - } + } + return &KubernetesDefaultRouter{ + logger: factory.logger, + flaggerClient: factory.flaggerClient, + kubeClient: factory.kubeClient, + labelSelector: labelSelector, + labelValue: labelValue, + ports: ports, } } diff --git a/pkg/router/gateway_api.go b/pkg/router/gateway_api.go index dd4ecd49f..290ec0617 100644 --- a/pkg/router/gateway_api.go +++ b/pkg/router/gateway_api.go @@ -59,16 +59,64 @@ type GatewayAPIRouter struct { setOwnerRefs bool } +func (gwr *GatewayAPIRouter) getServiceRef(canary *flaggerv1.Canary) (hostNames []v1.Hostname, apexSvcName, primarySvcName, primarySvcNamespace, canarySvcName, canarySvcNamespace string, err error) { + apexSvcName, primarySvcName, canarySvcName = canary.GetServiceNames() + canarySvcNamespace = canary.Namespace + primarySvcNamespace = canary.Namespace + err = nil + + for _, host := range canary.Spec.Service.Hosts { + hostNames = append(hostNames, v1.Hostname(host)) + } + + if canary.Spec.AutoscalerRef.Kind == "HTTPScaledObject" { + canarySvcName = "keda-http-add-on-interceptor-proxy" + canarySvcNamespace = "keda" + primarySvcNamespace = "keda" + targetHTTPSo, getErr := gwr.gatewayAPIClient.HttpV1alpha1().HTTPScaledObjects(canary.Namespace).Get(context.TODO(), canary.Spec.AutoscalerRef.Name, metav1.GetOptions{}) + if getErr != nil { + err = fmt.Errorf("HTTPScaledObject %s.%s get error: %w", canary.Spec.AutoscalerRef.Name, canary.Namespace, getErr) + return + } + for _, host := range targetHTTPSo.Spec.Hosts { + hostNames = append(hostNames, v1.Hostname(host)) + } + if canary.Spec.AutoscalerRef.CanaryInterceptorProxyService != nil { + canarySvcName = canary.Spec.AutoscalerRef.CanaryInterceptorProxyService.Name + if canary.Spec.AutoscalerRef.CanaryInterceptorProxyService.Namespace != "" { + canarySvcNamespace = canary.Spec.AutoscalerRef.CanaryInterceptorProxyService.Namespace + } + } + + if canary.Spec.AutoscalerRef.PrimaryScalingSet == nil { + err = fmt.Errorf("PrimaryScalingSet must be specified when using HTTPScaledObject as a Autoscaler.") + return + } + primarySvcName = fmt.Sprintf("%s-interceptor-proxy", canary.Spec.AutoscalerRef.PrimaryScalingSet.Name) + if canary.Spec.AutoscalerRef.PrimaryScalingSet.Namespace == "" { + if canary.Spec.AutoscalerRef.CanaryInterceptorProxyService != nil { + primarySvcNamespace = canary.Spec.AutoscalerRef.CanaryInterceptorProxyService.Namespace + } + } + if canary.Spec.AutoscalerRef.PrimaryScalingSet.Namespace != "" { + primarySvcNamespace = canary.Spec.AutoscalerRef.PrimaryScalingSet.Namespace + } + } + return +} + func (gwr *GatewayAPIRouter) Reconcile(canary *flaggerv1.Canary) error { if len(canary.Spec.Service.GatewayRefs) == 0 { return fmt.Errorf("GatewayRefs must be specified when using Gateway API as a provider.") } - apexSvcName, primarySvcName, canarySvcName := canary.GetServiceNames() + hostNames, apexSvcName, primarySvcName, primarySvcNamespace, canarySvcName, canarySvcNamespace, err := gwr.getServiceRef(canary) + if err != nil { + return fmt.Errorf("getServiceRef error: %w", err) + } hrNamespace := canary.Namespace - var hostNames []v1.Hostname for _, host := range canary.Spec.Service.Hosts { hostNames = append(hostNames, v1.Hostname(host)) } @@ -96,10 +144,10 @@ func (gwr *GatewayAPIRouter) Reconcile(canary *flaggerv1.Canary) error { Filters: gwr.makeFilters(canary), BackendRefs: []v1.HTTPBackendRef{ { - BackendRef: gwr.makeBackendRef(primarySvcName, initialPrimaryWeight, canary.Spec.Service.Port), + BackendRef: gwr.makeBackendRef(primarySvcName, primarySvcNamespace, initialPrimaryWeight, canary.Spec.Service.Port), }, { - BackendRef: gwr.makeBackendRef(canarySvcName, initialCanaryWeight, canary.Spec.Service.Port), + BackendRef: gwr.makeBackendRef(canarySvcName, canarySvcNamespace, initialCanaryWeight, canary.Spec.Service.Port), }, }, }, @@ -122,7 +170,7 @@ func (gwr *GatewayAPIRouter) Reconcile(canary *flaggerv1.Canary) error { Filters: gwr.makeFilters(canary), BackendRefs: []v1.HTTPBackendRef{ { - BackendRef: gwr.makeBackendRef(primarySvcName, initialPrimaryWeight, canary.Spec.Service.Port), + BackendRef: gwr.makeBackendRef(primarySvcName, primarySvcNamespace, initialPrimaryWeight, canary.Spec.Service.Port), }, }, }) @@ -246,7 +294,10 @@ func (gwr *GatewayAPIRouter) GetRoutes(canary *flaggerv1.Canary) ( mirrored bool, err error, ) { - apexSvcName, primarySvcName, canarySvcName := canary.GetServiceNames() + _, apexSvcName, primarySvcName, primarySvcNamespace, canarySvcName, canarySvcNamespace, err := gwr.getServiceRef(canary) + if err != nil { + return 0, 0, false, err + } hrNamespace := canary.Namespace httpRoute, err := gwr.gatewayAPIClient.GatewayapiV1().HTTPRoutes(hrNamespace).Get(context.TODO(), apexSvcName, metav1.GetOptions{}) if err != nil { @@ -269,10 +320,14 @@ func (gwr *GatewayAPIRouter) GetRoutes(canary *flaggerv1.Canary) ( // A/B testing: Avoid reading the rule with only for backendRef. if len(rule.BackendRefs) == 2 { for _, backendRef := range rule.BackendRefs { - if backendRef.Name == v1.ObjectName(primarySvcName) { + ns := httpRoute.Namespace + if backendRef.Namespace != nil { + ns = string(*backendRef.Namespace) + } + if backendRef.Name == v1.ObjectName(primarySvcName) && ns == primarySvcNamespace { primaryWeight = int(*backendRef.Weight) } - if backendRef.Name == v1.ObjectName(canarySvcName) { + if backendRef.Name == v1.ObjectName(canarySvcName) && ns == canarySvcNamespace { canaryWeight = int(*backendRef.Weight) } } @@ -304,19 +359,16 @@ func (gwr *GatewayAPIRouter) SetRoutes( canaryWeight int, mirrored bool, ) error { + hostNames, apexSvcName, primarySvcName, primarySvcNamespace, canarySvcName, canarySvcNamespace, err := gwr.getServiceRef(canary) + pWeight := int32(primaryWeight) cWeight := int32(canaryWeight) - apexSvcName, primarySvcName, canarySvcName := canary.GetServiceNames() hrNamespace := canary.Namespace httpRoute, err := gwr.gatewayAPIClient.GatewayapiV1().HTTPRoutes(hrNamespace).Get(context.TODO(), apexSvcName, metav1.GetOptions{}) if err != nil { return fmt.Errorf("HTTPRoute %s.%s get error: %w", apexSvcName, hrNamespace, err) } hrClone := httpRoute.DeepCopy() - hostNames := []v1.Hostname{} - for _, host := range canary.Spec.Service.Hosts { - hostNames = append(hostNames, v1.Hostname(host)) - } matches, err := gwr.mapRouteMatches(canary.Spec.Service.Match) if err != nil { return fmt.Errorf("Invalid request matching selectors: %w", err) @@ -339,10 +391,10 @@ func (gwr *GatewayAPIRouter) SetRoutes( Filters: gwr.makeFilters(canary), BackendRefs: []v1.HTTPBackendRef{ { - BackendRef: gwr.makeBackendRef(primarySvcName, pWeight, canary.Spec.Service.Port), + BackendRef: gwr.makeBackendRef(primarySvcName, primarySvcNamespace, pWeight, canary.Spec.Service.Port), }, { - BackendRef: gwr.makeBackendRef(canarySvcName, cWeight, canary.Spec.Service.Port), + BackendRef: gwr.makeBackendRef(canarySvcName, canarySvcNamespace, cWeight, canary.Spec.Service.Port), }, }, } @@ -398,7 +450,7 @@ func (gwr *GatewayAPIRouter) SetRoutes( Filters: gwr.makeFilters(canary), BackendRefs: []v1.HTTPBackendRef{ { - BackendRef: gwr.makeBackendRef(primarySvcName, initialPrimaryWeight, canary.Spec.Service.Port), + BackendRef: gwr.makeBackendRef(primarySvcName, primarySvcNamespace, pWeight, canary.Spec.Service.Port), }, }, Timeouts: &v1.HTTPRouteTimeouts{ @@ -430,7 +482,10 @@ func (gwr *GatewayAPIRouter) Finalize(_ *flaggerv1.Canary) error { // session affinity based Canary releases. func (gwr *GatewayAPIRouter) getSessionAffinityRouteRules(canary *flaggerv1.Canary, canaryWeight int, weightedRouteRule *v1.HTTPRouteRule) ([]v1.HTTPRouteRule, error) { - _, primarySvcName, canarySvcName := canary.GetServiceNames() + _, _, primarySvcName, primarySvcNamespace, canarySvcName, canarySvcNamespace, err := gwr.getServiceRef(canary) + if err != nil { + return nil, err + } stickyRouteRule := *weightedRouteRule // If a canary run is active, we want all responses corresponding to requests hitting the canary deployment @@ -483,10 +538,10 @@ func (gwr *GatewayAPIRouter) getSessionAffinityRouteRules(canary *flaggerv1.Cana stickyRouteRule.Matches = mergedMatches stickyRouteRule.BackendRefs = []v1.HTTPBackendRef{ { - BackendRef: gwr.makeBackendRef(primarySvcName, 0, canary.Spec.Service.Port), + BackendRef: gwr.makeBackendRef(primarySvcName, primarySvcNamespace, 0, canary.Spec.Service.Port), }, { - BackendRef: gwr.makeBackendRef(canarySvcName, 100, canary.Spec.Service.Port), + BackendRef: gwr.makeBackendRef(canarySvcName, canarySvcNamespace, 100, canary.Spec.Service.Port), }, } } else { @@ -610,13 +665,14 @@ func (gwr *GatewayAPIRouter) mapRouteMatches(requestMatches []istiov1beta1.HTTPM return matches, nil } -func (gwr *GatewayAPIRouter) makeBackendRef(svcName string, weight, port int32) v1.BackendRef { +func (gwr *GatewayAPIRouter) makeBackendRef(svcName, namespace string, weight, port int32) v1.BackendRef { return v1.BackendRef{ BackendObjectReference: v1.BackendObjectReference{ - Group: (*v1.Group)(&backendRefGroup), - Kind: (*v1.Kind)(&backendRefKind), - Name: v1.ObjectName(svcName), - Port: (*v1.PortNumber)(&port), + Group: (*v1.Group)(&backendRefGroup), + Kind: (*v1.Kind)(&backendRefKind), + Name: v1.ObjectName(svcName), + Namespace: (*v1.Namespace)(&namespace), + Port: (*v1.PortNumber)(&port), }, Weight: &weight, } diff --git a/pkg/router/kubernetes_default.go b/pkg/router/kubernetes_default.go index 840005672..4a6e6b453 100644 --- a/pkg/router/kubernetes_default.go +++ b/pkg/router/kubernetes_default.go @@ -68,6 +68,10 @@ func (c *KubernetesDefaultRouter) Initialize(canary *flaggerv1.Canary) error { func (c *KubernetesDefaultRouter) Reconcile(canary *flaggerv1.Canary) error { apexName, _, _ := canary.GetServiceNames() + if canary.Spec.AutoscalerRef != nil && canary.Spec.AutoscalerRef.Kind == "HTTPScaledObject" { + return nil + } + // main svc err := c.reconcileService(canary, apexName, fmt.Sprintf("%s-primary", c.labelValue), canary.Spec.Service.Apex) if err != nil {