diff --git a/artifacts/flagger/account.yaml b/artifacts/flagger/account.yaml index 311c91654..22c304474 100644 --- a/artifacts/flagger/account.yaml +++ b/artifacts/flagger/account.yaml @@ -110,6 +110,8 @@ rules: resources: - virtualnodes - virtualnodes/finalizers + - virtualrouters + - virtualrouters/finalizers - virtualservices - virtualservices/finalizers verbs: diff --git a/charts/flagger/templates/rbac.yaml b/charts/flagger/templates/rbac.yaml index c2ffb5a2a..506c17838 100644 --- a/charts/flagger/templates/rbac.yaml +++ b/charts/flagger/templates/rbac.yaml @@ -106,6 +106,8 @@ rules: resources: - virtualnodes - virtualnodes/finalizers + - virtualrouters + - virtualrouters/finalizers - virtualservices - virtualservices/finalizers verbs: diff --git a/docs/gitbook/tutorials/crossover-progressive-delivery.md b/docs/gitbook/tutorials/crossover-progressive-delivery.md index 8f92bfa02..970c28075 100644 --- a/docs/gitbook/tutorials/crossover-progressive-delivery.md +++ b/docs/gitbook/tutorials/crossover-progressive-delivery.md @@ -51,17 +51,6 @@ helm upgrade -i flagger flagger/flagger \ --set meshProvider=smi:crossover ``` -Optionally you can enable Slack notifications: - -```bash -helm upgrade -i flagger flagger/flagger \ ---reuse-values \ ---namespace test \ ---set slack.url=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK \ ---set slack.channel=general \ ---set slack.user=flagger -``` - ## Bootstrap Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler (HPA), @@ -82,6 +71,59 @@ helm upgrade -i flagger-loadtester flagger/loadtester \ --namespace=test ``` +Create a metric template to measure the HTTP requests error rate: + +```yaml +apiVersion: flagger.app/v1beta1 +kind: MetricTemplate +metadata: + name: error-rate + namespace: test +spec: + provider: + address: http://flagger-prometheus:9090 + type: prometheus + query: | + 100 - rate( + envoy_cluster_upstream_rq{ + kubernetes_namespace="{{ namespace }}", + envoy_cluster_name="{{ target }}-canary", + envoy_response_code!~"5.*" + }[{{ interval }}]) + / + rate( + envoy_cluster_upstream_rq{ + kubernetes_namespace="{{ namespace }}", + envoy_cluster_name="{{ target }}-canary" + }[{{ interval }}] + ) * 100 +``` + +Create a metric template to measure the HTTP requests average duration: + +```yaml +apiVersion: flagger.app/v1beta1 +kind: MetricTemplate +metadata: + name: latency + namespace: test +spec: + provider: + address: http://flagger-prometheus:9090 + type: prometheus + query: | + histogram_quantile(0.99, + sum( + rate( + envoy_cluster_upstream_rq_time_bucket{ + kubernetes_namespace="{{ namespace }}", + envoy_cluster_name="{{ target }}-canary" + }[{{ interval }}] + ) + ) by (le) + ) +``` + Create a canary custom resource: ```yaml @@ -91,15 +133,12 @@ metadata: name: podinfo namespace: test spec: - # specify mesh provider if it isn't the default one - # provider: "smi:crossover" + provider: "smi:crossover" # deployment reference targetRef: apiVersion: apps/v1 kind: Deployment name: podinfo - # the maximum time in seconds for the canary deployment - # to make progress before it is rollback (default 600s) progressDeadlineSeconds: 60 # HPA reference (optional) autoscalerRef: @@ -107,10 +146,7 @@ spec: kind: HorizontalPodAutoscaler name: podinfo service: - # ClusterIP port number port: 9898 - # container port number or name (optional) - targetPort: 9898 # define the canary analysis timing and KPIs analysis: # schedule interval (default 60s) @@ -123,21 +159,19 @@ spec: # canary increment step # percentage (0-100) stepWeight: 5 - # App Mesh Prometheus checks metrics: - - name: request-success-rate - # minimum req success rate (non 5xx responses) - # percentage (0-100) + - name: error-rate + templateRef: + name: error-rate thresholdRange: - min: 99 - interval: 1m - - name: request-duration - # maximum req duration P99 - # milliseconds + max: 1 + interval: 30s + - name: latency + templateRef: + name: latency thresholdRange: - max: 500 + max: 0.5 interval: 30s - # testing (optional) webhooks: - name: acceptance-test type: pre-rollout diff --git a/docs/gitbook/tutorials/prometheus-operator.md b/docs/gitbook/tutorials/prometheus-operator.md index ceb4bf88e..89066e3ff 100644 --- a/docs/gitbook/tutorials/prometheus-operator.md +++ b/docs/gitbook/tutorials/prometheus-operator.md @@ -118,7 +118,7 @@ spec: ) * 100 ``` -Amd a metric template to measure the HTTP requests average duration: +Create a metric template to measure the HTTP requests average duration: ```yaml apiVersion: flagger.app/v1beta1 diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index cd609cd5a..eaed5c604 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -30,7 +30,7 @@ chmod +x ${CODEGEN_PKG}/generate-groups.sh ${CODEGEN_PKG}/generate-groups.sh all \ github.com/weaveworks/flagger/pkg/client github.com/weaveworks/flagger/pkg/apis \ - "flagger:v1beta1 appmesh:v1beta1 istio:v1alpha3 smi:v1alpha1 smi:v1alpha2 gloo:v1 projectcontour:v1" \ + "flagger:v1beta1 appmesh:v1beta2 appmesh:v1beta1 istio:v1alpha3 smi:v1alpha1 smi:v1alpha2 gloo:v1 projectcontour:v1" \ --output-base "${TEMP_DIR}" \ --go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt diff --git a/kustomize/base/flagger/rbac.yaml b/kustomize/base/flagger/rbac.yaml index 5c9d102a4..e2a6b48d7 100644 --- a/kustomize/base/flagger/rbac.yaml +++ b/kustomize/base/flagger/rbac.yaml @@ -100,6 +100,8 @@ rules: resources: - virtualnodes - virtualnodes/finalizers + - virtualrouters + - virtualrouters/finalizers - virtualservices - virtualservices/finalizers verbs: diff --git a/pkg/apis/appmesh/v1beta2/doc.go b/pkg/apis/appmesh/v1beta2/doc.go new file mode 100644 index 000000000..bc912d340 --- /dev/null +++ b/pkg/apis/appmesh/v1beta2/doc.go @@ -0,0 +1,5 @@ +// +k8s:deepcopy-gen=package + +// Package v1beta2 is the v1beta2 version of the API. +// +groupName=appmesh.k8s.aws +package v1beta2 diff --git a/pkg/apis/appmesh/v1beta2/register.go b/pkg/apis/appmesh/v1beta2/register.go new file mode 100644 index 000000000..5cb0f231e --- /dev/null +++ b/pkg/apis/appmesh/v1beta2/register.go @@ -0,0 +1,41 @@ +package v1beta2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/weaveworks/flagger/pkg/apis/appmesh" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: appmesh.GroupName, Version: "v1beta2"} + +// 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 api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &VirtualService{}, + &VirtualServiceList{}, + &VirtualRouter{}, + &VirtualRouterList{}, + &VirtualNode{}, + &VirtualNodeList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/appmesh/v1beta2/types.go b/pkg/apis/appmesh/v1beta2/types.go new file mode 100644 index 000000000..324ea3514 --- /dev/null +++ b/pkg/apis/appmesh/v1beta2/types.go @@ -0,0 +1,91 @@ +package v1beta2 + +import "k8s.io/apimachinery/pkg/types" + +// +kubebuilder:validation:Enum=s;ms +type DurationUnit string + +const ( + DurationUnitS DurationUnit = "s" + DurationUnitMS DurationUnit = "ms" +) + +type Duration struct { + // A unit of time. + Unit DurationUnit `json:"unit"` + // A number of time units. + // +kubebuilder:validation:Minimum=0 + Value int64 `json:"value"` +} + +// +kubebuilder:validation:Minimum=1 +// +kubebuilder:validation:Maximum=65535 +type PortNumber int64 + +// +kubebuilder:validation:Enum=grpc;http;http2;tcp +type PortProtocol string + +const ( + PortProtocolGRPC PortProtocol = "grpc" + PortProtocolHTTP PortProtocol = "http" + PortProtocolHTTP2 PortProtocol = "http2" + PortProtocolTCP PortProtocol = "tcp" +) + +// PortMapping refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_PortMapping.html +type PortMapping struct { + // The port used for the port mapping. + Port PortNumber `json:"port"` + // The protocol used for the port mapping. + Protocol PortProtocol `json:"protocol"` +} + +// VirtualNodeReference holds a reference to VirtualNode.appmesh.k8s.aws +type VirtualNodeReference struct { + // Namespace is the namespace of VirtualNode CR. + // If unspecified, defaults to the referencing object's namespace + // +optional + Namespace *string `json:"namespace,omitempty"` + // Name is the name of VirtualNode CR + Name string `json:"name"` +} + +// VirtualServiceReference holds a reference to VirtualService.appmesh.k8s.aws +type VirtualServiceReference struct { + // Namespace is the namespace of VirtualService CR. + // If unspecified, defaults to the referencing object's namespace + // +optional + Namespace *string `json:"namespace,omitempty"` + // Name is the name of VirtualService CR + Name string `json:"name"` +} + +// VirtualRouterReference holds a reference to VirtualRouter.appmesh.k8s.aws +type VirtualRouterReference struct { + // Namespace is the namespace of VirtualRouter CR. + // If unspecified, defaults to the referencing object's namespace + // +optional + Namespace *string `json:"namespace,omitempty"` + // Name is the name of VirtualRouter CR + Name string `json:"name"` +} + +// MeshReference holds a reference to Mesh.appmesh.k8s.aws +type MeshReference struct { + // Name is the name of Mesh CR + Name string `json:"name"` + // UID is the UID of Mesh CR + UID types.UID `json:"uid"` +} + +// VirtualGatewayReference holds a reference to VirtualGateway.appmesh.k8s.aws +type VirtualGatewayReference struct { + // Namespace is the namespace of VirtualGateway CR. + // If unspecified, defaults to the referencing object's namespace + // +optional + Namespace *string `json:"namespace,omitempty"` + // Name is the name of VirtualGateway CR + Name string `json:"name"` + // UID is the UID of VirtualGateway CR + UID types.UID `json:"uid"` +} diff --git a/pkg/apis/appmesh/v1beta2/virtualnode_types.go b/pkg/apis/appmesh/v1beta2/virtualnode_types.go new file mode 100644 index 000000000..48b29f48f --- /dev/null +++ b/pkg/apis/appmesh/v1beta2/virtualnode_types.go @@ -0,0 +1,347 @@ +package v1beta2 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TLSValidationContextACMTrust refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_TlsValidationContextAcmTrust.html +type TLSValidationContextACMTrust struct { + // One or more ACM Amazon Resource Name (ARN)s. + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=3 + CertificateAuthorityARNs []string `json:"certificateAuthorityARNs"` +} + +// TLSValidationContextFileTrust refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_TlsValidationContextFileTrust.html +type TLSValidationContextFileTrust struct { + // The certificate trust chain for a certificate stored on the file system of the virtual node that the proxy is running on. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + CertificateChain string `json:"certificateChain"` +} + +// TLSValidationContextTrust refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_TlsValidationContextTrust.html +type TLSValidationContextTrust struct { + // A reference to an object that represents a TLS validation context trust for an AWS Certicate Manager (ACM) certificate. + // +optional + ACM *TLSValidationContextACMTrust `json:"acm,omitempty"` + // An object that represents a TLS validation context trust for a local file. + // +optional + File *TLSValidationContextFileTrust `json:"file,omitempty"` +} + +// TLSValidationContext refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_TlsValidationContext.html +type TLSValidationContext struct { + // A reference to an object that represents a TLS validation context trust + Trust TLSValidationContextTrust `json:"trust"` +} + +// ClientPolicyTLS refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_ClientPolicyTls.html +type ClientPolicyTLS struct { + // Whether the policy is enforced. + // If unspecified, default settings from AWS API will be applied. Refer to AWS Docs for default settings. + // +optional + Enforce *bool `json:"enforce,omitempty"` + // The range of ports that the policy is enforced for. + // +optional + Ports []PortNumber `json:"ports,omitempty"` + // A reference to an object that represents a TLS validation context. + Validation TLSValidationContext `json:"validation"` +} + +// ClientPolicy refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_ClientPolicy.html +type ClientPolicy struct { + // A reference to an object that represents a Transport Layer Security (TLS) client policy. + // +optional + TLS *ClientPolicyTLS `json:"tls,omitempty"` +} + +// VirtualServiceBackend refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_VirtualServiceBackend.html +type VirtualServiceBackend struct { + // The VirtualService that is acting as a virtual node backend. + VirtualServiceRef VirtualServiceReference `json:"virtualServiceRef"` + // A reference to an object that represents the client policy for a backend. + // +optional + ClientPolicy *ClientPolicy `json:"clientPolicy,omitempty"` +} + +// Backend refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_Backend.html +type Backend struct { + // Specifies a virtual service to use as a backend for a virtual node. + VirtualService VirtualServiceBackend `json:"virtualService"` +} + +// BackendDefaults refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_BackendDefaults.html +type BackendDefaults struct { + // A reference to an object that represents a client policy. + // +optional + ClientPolicy *ClientPolicy `json:"clientPolicy,omitempty"` +} + +// HealthCheckPolicy refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_HealthCheckPolicy.html +type HealthCheckPolicy struct { + // The number of consecutive successful health checks that must occur before declaring listener healthy. + // If unspecified, defaults to be 10 + // +kubebuilder:validation:Minimum=2 + // +kubebuilder:validation:Maximum=10 + // +optional + HealthyThreshold *int64 `json:"healthyThreshold,omitempty"` + // The time period in milliseconds between each health check execution. + // If unspecified, defaults to be 30000 + // +kubebuilder:validation:Minimum=5000 + // +kubebuilder:validation:Maximum=300000 + // +optional + IntervalMillis *int64 `json:"intervalMillis,omitempty"` + // The destination path for the health check request. + // This value is only used if the specified protocol is http or http2. For any other protocol, this value is ignored. + // +optional + Path *string `json:"path,omitempty"` + // The destination port for the health check request. + // If unspecified, defaults to be same as port defined in the PortMapping for the listener. + // +optional + Port *PortNumber `json:"port,omitempty"` + // The protocol for the health check request + // If unspecified, defaults to be same as protocol defined in the PortMapping for the listener. + // +optional + Protocol *PortProtocol `json:"protocol,omitempty"` + // The amount of time to wait when receiving a response from the health check, in milliseconds. + // If unspecified, defaults to be 5000 + // +kubebuilder:validation:Minimum=2000 + // +kubebuilder:validation:Maximum=60000 + // +optional + TimeoutMillis *int64 `json:"timeoutMillis,omitempty"` + // The number of consecutive failed health checks that must occur before declaring a virtual node unhealthy. + // If unspecified, defaults to be 2 + // +kubebuilder:validation:Minimum=2 + // +kubebuilder:validation:Maximum=10 + // +optional + UnhealthyThreshold *int64 `json:"unhealthyThreshold,omitempty"` +} + +// ListenerTLSACMCertificate refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_ListenerTlsAcmCertificate.html +type ListenerTLSACMCertificate struct { + // The Amazon Resource Name (ARN) for the certificate. + CertificateARN string `json:"certificateARN"` +} + +// ListenerTLSFileCertificate refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_ListenerTlsFileCertificate.html +type ListenerTLSFileCertificate struct { + // The certificate chain for the certificate. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + CertificateChain string `json:"certificateChain"` + // The private key for a certificate stored on the file system of the virtual node that the proxy is running on. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + PrivateKey string `json:"privateKey"` +} + +// ListenerTLSCertificate refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_ListenerTlsCertificate.html +type ListenerTLSCertificate struct { + // A reference to an object that represents an AWS Certificate Manager (ACM) certificate. + // +optional + ACM *ListenerTLSACMCertificate `json:"acm,omitempty"` + // A reference to an object that represents a local file certificate. + // +optional + File *ListenerTLSFileCertificate `json:"file,omitempty"` +} + +const ( + ListenerTLSModeDisabled ListenerTLSMode = "DISABLED" + ListenerTLSModePermissive ListenerTLSMode = "PERMISSIVE" + ListenerTLSModeStrict ListenerTLSMode = "STRICT" +) + +// +kubebuilder:validation:Enum=DISABLED;PERMISSIVE;STRICT +type ListenerTLSMode string + +// ListenerTLS refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_ListenerTls.html +type ListenerTLS struct { + // A reference to an object that represents a listener's TLS certificate. + Certificate ListenerTLSCertificate `json:"certificate"` + // ListenerTLS mode + Mode ListenerTLSMode `json:"mode"` +} + +// Listener refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_Listener.html +type Listener struct { + // The port mapping information for the listener. + PortMapping PortMapping `json:"portMapping"` + // The health check information for the listener. + // +optional + HealthCheck *HealthCheckPolicy `json:"healthCheck,omitempty"` + // A reference to an object that represents the Transport Layer Security (TLS) properties for a listener. + // +optional + TLS *ListenerTLS `json:"tls,omitempty"` +} + +// AWSCloudMapInstanceAttribute refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_AwsCloudMapInstanceAttribute.html +type AWSCloudMapInstanceAttribute struct { + // The name of an AWS Cloud Map service instance attribute key. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + Key string `json:"key"` + // The value of an AWS Cloud Map service instance attribute key. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1024 + Value string `json:"value"` +} + +// AWSCloudMapServiceDiscovery refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_AwsCloudMapServiceDiscovery.html +type AWSCloudMapServiceDiscovery struct { + // The name of the AWS Cloud Map namespace to use. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1024 + NamespaceName string `json:"namespaceName"` + // The name of the AWS Cloud Map service to use. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1024 + ServiceName string `json:"serviceName"` + // A string map that contains attributes with values that you can use to filter instances by any custom attribute that you specified when you registered the instance + // +optional + Attributes []AWSCloudMapInstanceAttribute `json:"attributes,omitempty"` +} + +// DNSServiceDiscovery refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_DnsServiceDiscovery.html +type DNSServiceDiscovery struct { + // Specifies the DNS service discovery hostname for the virtual node. + Hostname string `json:"hostname"` +} + +// ServiceDiscovery refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_ServiceDiscovery.html +type ServiceDiscovery struct { + // Specifies any AWS Cloud Map information for the virtual node. + // +optional + AWSCloudMap *AWSCloudMapServiceDiscovery `json:"awsCloudMap,omitempty"` + // Specifies the DNS information for the virtual node. + // +optional + DNS *DNSServiceDiscovery `json:"dns,omitempty"` +} + +// FileAccessLog refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_FileAccessLog.html +type FileAccessLog struct { + // The file path to write access logs to. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + Path string `json:"path"` +} + +// AccessLog refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_AccessLog.html +type AccessLog struct { + // The file object to send virtual node access logs to. + // +optional + File *FileAccessLog `json:"file,omitempty"` +} + +// Logging refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_Logging.html +type Logging struct { + // The access log configuration for a virtual node. + // +optional + AccessLog *AccessLog `json:"accessLog,omitempty"` +} + +type VirtualNodeConditionType string + +const ( + // VirtualNodeActive is True when the AppMesh VirtualNode has been created or found via the API + VirtualNodeActive VirtualNodeConditionType = "VirtualNodeActive" +) + +type VirtualNodeCondition struct { + // Type of VirtualNode condition. + Type VirtualNodeConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus `json:"status"` + // Last time the condition transitioned from one status to another. + // +optional + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` + // The reason for the condition's last transition. + // +optional + Reason *string `json:"reason,omitempty"` + // A human readable message indicating details about the transition. + // +optional + Message *string `json:"message,omitempty"` +} + +// AWSCloudMapServiceStatus is AWS CloudMap Service object's info +type AWSCloudMapServiceStatus struct { + // NamespaceID is AWS CloudMap Service object's namespace Id + // +optional + NamespaceID *string `json:"namespaceID,omitempty"` + // ServiceID is AWS CloudMap Service object's Id + // +optional + ServiceID *string `json:"serviceID,omitempty"` +} + +// VirtualNodeSpec defines the desired state of VirtualNode +// refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_VirtualServiceSpec.html +type VirtualNodeSpec struct { + // AWSName is the AppMesh VirtualNode object's name. + // If unspecified or empty, it defaults to be "${name}_${namespace}" of k8s VirtualNode + // +optional + AWSName *string `json:"awsName,omitempty"` + // PodSelector selects Pods using labels to designate VirtualNode membership. + // if unspecified or empty, it selects no pods. + // +optional + PodSelector *metav1.LabelSelector `json:"podSelector,omitempty"` + // The listener that the virtual node is expected to receive inbound traffic from + // +kubebuilder:validation:MinItems=0 + // +kubebuilder:validation:MaxItems=1 + // +optional + Listeners []Listener `json:"listeners,omitempty"` + // The service discovery information for the virtual node. + // +optional + ServiceDiscovery *ServiceDiscovery `json:"serviceDiscovery,omitempty"` + // The backends that the virtual node is expected to send outbound traffic to. + // +optional + Backends []Backend `json:"backends,omitempty"` + // A reference to an object that represents the defaults for backends. + // +optional + BackendDefaults *BackendDefaults `json:"backendDefaults,omitempty"` + // The inbound and outbound access logging information for the virtual node. + // +optional + Logging *Logging `json:"logging,omitempty"` + + // A reference to k8s Mesh CR that this VirtualNode belongs to. + // The admission controller populates it using Meshes's selector, and prevents users from setting this field. + // + // Populated by the system. + // Read-only. + // +optional + MeshRef *MeshReference `json:"meshRef,omitempty"` +} + +// VirtualNodeStatus defines the observed state of VirtualNode +type VirtualNodeStatus struct { + // VirtualNodeARN is the AppMesh VirtualNode object's Amazon Resource Name + // +optional + VirtualNodeARN *string `json:"virtualNodeARN,omitempty"` + // The current VirtualNode status. + // +optional + Conditions []VirtualNodeCondition `json:"conditions,omitempty"` + // AWSCloudMapServiceStatus is AWS CloudMap Service object's info + // +optional + AWSCloudMapServiceStatus *AWSCloudMapServiceStatus `json:"awsCloudMapServiceStatus,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VirtualNode is the Schema for the virtualnodes API +type VirtualNode struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VirtualNodeSpec `json:"spec,omitempty"` + Status VirtualNodeStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VirtualNodeList contains a list of VirtualNode +type VirtualNodeList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualNode `json:"items"` +} diff --git a/pkg/apis/appmesh/v1beta2/virtualrouter_types.go b/pkg/apis/appmesh/v1beta2/virtualrouter_types.go new file mode 100644 index 000000000..e4b3674a9 --- /dev/null +++ b/pkg/apis/appmesh/v1beta2/virtualrouter_types.go @@ -0,0 +1,369 @@ +/* + + +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 v1beta2 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// VirtualRouterListener refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_VirtualRouterListener.html +type VirtualRouterListener struct { + // The port mapping information for the listener. + PortMapping PortMapping `json:"portMapping"` +} + +// WeightedTarget refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_WeightedTarget.html +type WeightedTarget struct { + // The virtual node to associate with the weighted target. + VirtualNodeRef VirtualNodeReference `json:"virtualNodeRef"` + // The relative weight of the weighted target. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=100 + Weight int64 `json:"weight"` +} + +type MatchRange struct { + // The start of the range. + // +optional + Start int64 `json:"start"` + // The end of the range. + // +optional + End int64 `json:"end"` +} + +// HeaderMatchMethod refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_HeaderMatchMethod.html +type HeaderMatchMethod struct { + // The value sent by the client must match the specified value exactly. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + // +optional + Exact *string `json:"exact,omitempty"` + // The value sent by the client must begin with the specified characters. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + // +optional + Prefix *string `json:"prefix,omitempty"` + // An object that represents the range of values to match on. + // +optional + Range *MatchRange `json:"range,omitempty"` + // The value sent by the client must include the specified characters. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + // +optional + Regex *string `json:"regex,omitempty"` + // The value sent by the client must end with the specified characters. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + // +optional + Suffix *string `json:"suffix,omitempty"` +} + +// HTTPRouteHeader refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_HttpRouteHeader.html +type HTTPRouteHeader struct { + // A name for the HTTP header in the client request that will be matched on. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=50 + Name string `json:"name"` + // The HeaderMatchMethod object. + // +optional + Match *HeaderMatchMethod `json:"match,omitempty"` + // Specify True to match anything except the match criteria. The default value is False. + // +optional + Invert *bool `json:"invert,omitempty"` +} + +// HTTPRouteMatch refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_HttpRouteMatch.html +type HTTPRouteMatch struct { + // An object that represents the client request headers to match on. + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=10 + // +optional + Headers []HTTPRouteHeader `json:"headers,omitempty"` + // The client request method to match on. + // +kubebuilder:validation:Enum=CONNECT;DELETE;GET;HEAD;OPTIONS;PATCH;POST;PUT;TRACE + // +optional + Method *string `json:"method,omitempty"` + // Specifies the path to match requests with + Prefix string `json:"prefix"` + // The client request scheme to match on + // +kubebuilder:validation:Enum=http;https + // +optional + Scheme *string `json:"scheme,omitempty"` +} + +// HTTPRouteAction refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_HttpRouteAction.html +type HTTPRouteAction struct { + // An object that represents the targets that traffic is routed to when a request matches the route. + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=10 + WeightedTargets []WeightedTarget `json:"weightedTargets"` +} + +// +kubebuilder:validation:Enum=server-error;gateway-error;client-error;stream-error +type HTTPRetryPolicyEvent string + +// +kubebuilder:validation:Enum=connection-error +type TCPRetryPolicyEvent string + +// +kubebuilder:validation:Enum=cancelled;deadline-exceeded;internal;resource-exhausted;unavailable +type GRPCRetryPolicyEvent string + +// HTTPRetryPolicy refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_HttpRetryPolicy.html +type HTTPRetryPolicy struct { + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=25 + // +optional + HTTPRetryEvents []HTTPRetryPolicyEvent `json:"httpRetryEvents,omitempty"` + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=1 + // +optional + TCPRetryEvents []TCPRetryPolicyEvent `json:"tcpRetryEvents,omitempty"` + // The maximum number of retry attempts. + // +kubebuilder:validation:Minimum=0 + MaxRetries int64 `json:"maxRetries"` + // An object that represents a duration of time + PerRetryTimeout Duration `json:"perRetryTimeout"` +} + +// HTTPRoute refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_HttpRoute.html +type HTTPRoute struct { + // An object that represents the criteria for determining a request match. + Match HTTPRouteMatch `json:"match"` + // An object that represents the action to take if a match is determined. + Action HTTPRouteAction `json:"action"` + // An object that represents a retry policy. + // +optional + RetryPolicy *HTTPRetryPolicy `json:"retryPolicy,omitempty"` +} + +// TCPRouteAction refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_TcpRouteAction.html +type TCPRouteAction struct { + // An object that represents the targets that traffic is routed to when a request matches the route. + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=10 + WeightedTargets []WeightedTarget `json:"weightedTargets"` +} + +// TCPRoute refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_TcpRoute.html +type TCPRoute struct { + // The action to take if a match is determined. + Action TCPRouteAction `json:"action"` +} + +// GRPCRouteMetadataMatchMethod refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_GrpcRouteMetadataMatchMethod.html +type GRPCRouteMetadataMatchMethod struct { + // The value sent by the client must match the specified value exactly. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + // +optional + Exact *string `json:"exact,omitempty"` + // The value sent by the client must begin with the specified characters. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + // +optional + Prefix *string `json:"prefix,omitempty"` + // An object that represents the range of values to match on + // +optional + Range *MatchRange `json:"range,omitempty"` + // The value sent by the client must include the specified characters. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + // +optional + Regex *string `json:"regex,omitempty"` + // The value sent by the client must end with the specified characters. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + // +optional + Suffix *string `json:"suffix,omitempty"` +} + +// GRPCRouteMetadata refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_GrpcRouteMetadata.html +type GRPCRouteMetadata struct { + // The name of the route. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=50 + Name string `json:"name"` + // An object that represents the data to match from the request. + // +optional + Match *GRPCRouteMetadataMatchMethod `json:"match,omitempty"` + // Specify True to match anything except the match criteria. The default value is False. + // +optional + Invert *bool `json:"invert,omitempty"` +} + +// GRPCRouteMatch refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_GrpcRouteMatch.html +type GRPCRouteMatch struct { + // The method name to match from the request. If you specify a name, you must also specify a serviceName. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=50 + // +optional + MethodName *string `json:"methodName,omitempty"` + // The fully qualified domain name for the service to match from the request. + // +optional + ServiceName *string `json:"serviceName,omitempty"` + // An object that represents the data to match from the request. + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=10 + // +optional + Metadata []GRPCRouteMetadata `json:"metadata,omitempty"` +} + +// GRPCRouteAction refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_GrpcRouteAction.html +type GRPCRouteAction struct { + // An object that represents the targets that traffic is routed to when a request matches the route. + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=10 + WeightedTargets []WeightedTarget `json:"weightedTargets"` +} + +// GRPCRetryPolicy refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_GrpcRetryPolicy.html +type GRPCRetryPolicy struct { + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=5 + // +optional + GRPCRetryEvents []GRPCRetryPolicyEvent `json:"grpcRetryEvents,omitempty"` + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=25 + // +optional + HTTPRetryEvents []HTTPRetryPolicyEvent `json:"httpRetryEvents,omitempty"` + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=1 + // +optional + TCPRetryEvents []TCPRetryPolicyEvent `json:"tcpRetryEvents,omitempty"` + // The maximum number of retry attempts. + // +kubebuilder:validation:Minimum=0 + MaxRetries int64 `json:"maxRetries"` + // An object that represents a duration of time. + PerRetryTimeout Duration `json:"perRetryTimeout"` +} + +// GRPCRoute refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_GrpcRoute.html +type GRPCRoute struct { + // An object that represents the criteria for determining a request match. + Match GRPCRouteMatch `json:"match"` + // An object that represents the action to take if a match is determined. + Action GRPCRouteAction `json:"action"` + // An object that represents a retry policy. + // +optional + RetryPolicy *GRPCRetryPolicy `json:"retryPolicy,omitempty"` +} + +// Route refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_RouteSpec.html +type Route struct { + // Route's name + Name string `json:"name"` + // An object that represents the specification of a gRPC route. + // +optional + GRPCRoute *GRPCRoute `json:"grpcRoute,omitempty"` + // An object that represents the specification of an HTTP route. + // +optional + HTTPRoute *HTTPRoute `json:"httpRoute,omitempty"` + // An object that represents the specification of an HTTP/2 route. + // +optional + HTTP2Route *HTTPRoute `json:"http2Route,omitempty"` + // An object that represents the specification of a TCP route. + // +optional + TCPRoute *TCPRoute `json:"tcpRoute,omitempty"` + // The priority for the route. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=1000 + // +optional + Priority *int64 `json:"priority,omitempty"` +} + +type VirtualRouterConditionType string + +const ( + // VirtualRouterActive is True when the AppMesh VirtualRouter has been created or found via the API + VirtualRouterActive VirtualRouterConditionType = "VirtualRouterActive" +) + +type VirtualRouterCondition struct { + // Type of VirtualRouter condition. + Type VirtualRouterConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus `json:"status"` + // Last time the condition transitioned from one status to another. + // +optional + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` + // The reason for the condition's last transition. + // +optional + Reason *string `json:"reason,omitempty"` + // A human readable message indicating details about the transition. + // +optional + Message *string `json:"message,omitempty"` +} + +// VirtualRouterSpec defines the desired state of VirtualRouter +// refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_VirtualRouterSpec.html +type VirtualRouterSpec struct { + // AWSName is the AppMesh VirtualRouter object's name. + // If unspecified or empty, it defaults to be "${name}_${namespace}" of k8s VirtualRouter + // +optional + AWSName *string `json:"awsName,omitempty"` + // The listeners that the virtual router is expected to receive inbound traffic from + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=1 + Listeners []VirtualRouterListener `json:"listeners,omitempty"` + + // The routes associated with VirtualRouter + // +optional + Routes []Route `json:"routes,omitempty"` + + // A reference to k8s Mesh CR that this VirtualRouter belongs to. + // The admission controller populates it using Meshes's selector, and prevents users from setting this field. + // + // Populated by the system. + // Read-only. + // +optional + MeshRef *MeshReference `json:"meshRef,omitempty"` +} + +// VirtualRouterStatus defines the observed state of VirtualRouter +type VirtualRouterStatus struct { + // VirtualRouterARN is the AppMesh VirtualRouter object's Amazon Resource Name. + // +optional + VirtualRouterARN *string `json:"virtualRouterARN,omitempty"` + // RouteARNs is a map of AppMesh Route objects' Amazon Resource Names, indexed by route name. + // +optional + RouteARNs map[string]string `json:"routeARNs,omitempty"` + // The current VirtualRouter status. + // +optional + Conditions []VirtualRouterCondition `json:"conditions,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VirtualRouter is the Schema for the virtualrouters API +type VirtualRouter struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VirtualRouterSpec `json:"spec,omitempty"` + Status VirtualRouterStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VirtualRouterList contains a list of VirtualRouter +type VirtualRouterList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualRouter `json:"items"` +} diff --git a/pkg/apis/appmesh/v1beta2/virtualservice_types.go b/pkg/apis/appmesh/v1beta2/virtualservice_types.go new file mode 100644 index 000000000..2c7d9d510 --- /dev/null +++ b/pkg/apis/appmesh/v1beta2/virtualservice_types.go @@ -0,0 +1,118 @@ +/* + + +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 v1beta2 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// VirtualNodeServiceProvider refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_VirtualNodeServiceProvider.html +type VirtualNodeServiceProvider struct { + // The virtual node that is acting as a service provider. + VirtualNodeRef VirtualNodeReference `json:"virtualNodeRef"` +} + +// VirtualRouterServiceProvider refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_VirtualRouterServiceProvider.html +type VirtualRouterServiceProvider struct { + // The virtual router that is acting as a service provider. + VirtualRouterRef VirtualRouterReference `json:"virtualRouterRef"` +} + +// VirtualServiceProvider refers to https://docs.aws.amazon.com/app-mesh/latest/APIReference/API_VirtualServiceProvider.html +type VirtualServiceProvider struct { + // The virtual node associated with a virtual service. + // +optional + VirtualNode *VirtualNodeServiceProvider `json:"virtualNode,omitempty"` + // The virtual router associated with a virtual service. + // +optional + VirtualRouter *VirtualRouterServiceProvider `json:"virtualRouter,omitempty"` +} + +type VirtualServiceConditionType string + +const ( + // VirtualServiceActive is True when the AppMesh VirtualService has been created or found via the API + VirtualServiceActive VirtualServiceConditionType = "VirtualServiceActive" +) + +type VirtualServiceCondition struct { + // Type of VirtualService condition. + Type VirtualServiceConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus `json:"status"` + // Last time the condition transitioned from one status to another. + // +optional + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` + // The reason for the condition's last transition. + // +optional + Reason *string `json:"reason,omitempty"` + // A human readable message indicating details about the transition. + // +optional + Message *string `json:"message,omitempty"` +} + +// VirtualServiceSpec defines the desired state of VirtualService +type VirtualServiceSpec struct { + // AWSName is the AppMesh VirtualService object's name. + // If unspecified or empty, it defaults to be "${name}.${namespace}" of k8s VirtualService + // +optional + AWSName *string `json:"awsName,omitempty"` + + // The provider for virtual services. You can specify a single virtual node or virtual router. + // +optional + Provider *VirtualServiceProvider `json:"provider,omitempty"` + + // A reference to k8s Mesh CR that this VirtualService belongs to. + // The admission controller populates it using Meshes's selector, and prevents users from setting this field. + // + // Populated by the system. + // Read-only. + // +optional + MeshRef *MeshReference `json:"meshRef,omitempty"` +} + +// VirtualServiceStatus defines the observed state of VirtualService +type VirtualServiceStatus struct { + // VirtualServiceARN is the AppMesh VirtualService object's Amazon Resource Name. + // +optional + VirtualServiceARN *string `json:"virtualServiceARN,omitempty"` + // The current VirtualService status. + // +optional + Conditions []VirtualServiceCondition `json:"conditions,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VirtualService is the Schema for the virtualservices API +type VirtualService struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VirtualServiceSpec `json:"spec,omitempty"` + Status VirtualServiceStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VirtualServiceList contains a list of VirtualService +type VirtualServiceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VirtualService `json:"items"` +} diff --git a/pkg/apis/appmesh/v1beta2/zz_generated.deepcopy.go b/pkg/apis/appmesh/v1beta2/zz_generated.deepcopy.go new file mode 100644 index 000000000..9e5fe7dc3 --- /dev/null +++ b/pkg/apis/appmesh/v1beta2/zz_generated.deepcopy.go @@ -0,0 +1,1702 @@ +// +build !ignore_autogenerated + +/* +Copyright The Flagger 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 v1beta2 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/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 *AWSCloudMapInstanceAttribute) DeepCopyInto(out *AWSCloudMapInstanceAttribute) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSCloudMapInstanceAttribute. +func (in *AWSCloudMapInstanceAttribute) DeepCopy() *AWSCloudMapInstanceAttribute { + if in == nil { + return nil + } + out := new(AWSCloudMapInstanceAttribute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSCloudMapServiceDiscovery) DeepCopyInto(out *AWSCloudMapServiceDiscovery) { + *out = *in + if in.Attributes != nil { + in, out := &in.Attributes, &out.Attributes + *out = make([]AWSCloudMapInstanceAttribute, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSCloudMapServiceDiscovery. +func (in *AWSCloudMapServiceDiscovery) DeepCopy() *AWSCloudMapServiceDiscovery { + if in == nil { + return nil + } + out := new(AWSCloudMapServiceDiscovery) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSCloudMapServiceStatus) DeepCopyInto(out *AWSCloudMapServiceStatus) { + *out = *in + if in.NamespaceID != nil { + in, out := &in.NamespaceID, &out.NamespaceID + *out = new(string) + **out = **in + } + if in.ServiceID != nil { + in, out := &in.ServiceID, &out.ServiceID + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSCloudMapServiceStatus. +func (in *AWSCloudMapServiceStatus) DeepCopy() *AWSCloudMapServiceStatus { + if in == nil { + return nil + } + out := new(AWSCloudMapServiceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AccessLog) DeepCopyInto(out *AccessLog) { + *out = *in + if in.File != nil { + in, out := &in.File, &out.File + *out = new(FileAccessLog) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccessLog. +func (in *AccessLog) DeepCopy() *AccessLog { + if in == nil { + return nil + } + out := new(AccessLog) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Backend) DeepCopyInto(out *Backend) { + *out = *in + in.VirtualService.DeepCopyInto(&out.VirtualService) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backend. +func (in *Backend) DeepCopy() *Backend { + if in == nil { + return nil + } + out := new(Backend) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendDefaults) DeepCopyInto(out *BackendDefaults) { + *out = *in + if in.ClientPolicy != nil { + in, out := &in.ClientPolicy, &out.ClientPolicy + *out = new(ClientPolicy) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendDefaults. +func (in *BackendDefaults) DeepCopy() *BackendDefaults { + if in == nil { + return nil + } + out := new(BackendDefaults) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientPolicy) DeepCopyInto(out *ClientPolicy) { + *out = *in + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(ClientPolicyTLS) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientPolicy. +func (in *ClientPolicy) DeepCopy() *ClientPolicy { + if in == nil { + return nil + } + out := new(ClientPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientPolicyTLS) DeepCopyInto(out *ClientPolicyTLS) { + *out = *in + if in.Enforce != nil { + in, out := &in.Enforce, &out.Enforce + *out = new(bool) + **out = **in + } + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]PortNumber, len(*in)) + copy(*out, *in) + } + in.Validation.DeepCopyInto(&out.Validation) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientPolicyTLS. +func (in *ClientPolicyTLS) DeepCopy() *ClientPolicyTLS { + if in == nil { + return nil + } + out := new(ClientPolicyTLS) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNSServiceDiscovery) DeepCopyInto(out *DNSServiceDiscovery) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSServiceDiscovery. +func (in *DNSServiceDiscovery) DeepCopy() *DNSServiceDiscovery { + if in == nil { + return nil + } + out := new(DNSServiceDiscovery) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Duration) DeepCopyInto(out *Duration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Duration. +func (in *Duration) DeepCopy() *Duration { + if in == nil { + return nil + } + out := new(Duration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FileAccessLog) DeepCopyInto(out *FileAccessLog) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileAccessLog. +func (in *FileAccessLog) DeepCopy() *FileAccessLog { + if in == nil { + return nil + } + out := new(FileAccessLog) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRetryPolicy) DeepCopyInto(out *GRPCRetryPolicy) { + *out = *in + if in.GRPCRetryEvents != nil { + in, out := &in.GRPCRetryEvents, &out.GRPCRetryEvents + *out = make([]GRPCRetryPolicyEvent, len(*in)) + copy(*out, *in) + } + if in.HTTPRetryEvents != nil { + in, out := &in.HTTPRetryEvents, &out.HTTPRetryEvents + *out = make([]HTTPRetryPolicyEvent, len(*in)) + copy(*out, *in) + } + if in.TCPRetryEvents != nil { + in, out := &in.TCPRetryEvents, &out.TCPRetryEvents + *out = make([]TCPRetryPolicyEvent, len(*in)) + copy(*out, *in) + } + out.PerRetryTimeout = in.PerRetryTimeout + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRetryPolicy. +func (in *GRPCRetryPolicy) DeepCopy() *GRPCRetryPolicy { + if in == nil { + return nil + } + out := new(GRPCRetryPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRoute) DeepCopyInto(out *GRPCRoute) { + *out = *in + in.Match.DeepCopyInto(&out.Match) + in.Action.DeepCopyInto(&out.Action) + if in.RetryPolicy != nil { + in, out := &in.RetryPolicy, &out.RetryPolicy + *out = new(GRPCRetryPolicy) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRoute. +func (in *GRPCRoute) DeepCopy() *GRPCRoute { + if in == nil { + return nil + } + out := new(GRPCRoute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRouteAction) DeepCopyInto(out *GRPCRouteAction) { + *out = *in + if in.WeightedTargets != nil { + in, out := &in.WeightedTargets, &out.WeightedTargets + *out = make([]WeightedTarget, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteAction. +func (in *GRPCRouteAction) DeepCopy() *GRPCRouteAction { + if in == nil { + return nil + } + out := new(GRPCRouteAction) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRouteMatch) DeepCopyInto(out *GRPCRouteMatch) { + *out = *in + if in.MethodName != nil { + in, out := &in.MethodName, &out.MethodName + *out = new(string) + **out = **in + } + if in.ServiceName != nil { + in, out := &in.ServiceName, &out.ServiceName + *out = new(string) + **out = **in + } + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = make([]GRPCRouteMetadata, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteMatch. +func (in *GRPCRouteMatch) DeepCopy() *GRPCRouteMatch { + if in == nil { + return nil + } + out := new(GRPCRouteMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRouteMetadata) DeepCopyInto(out *GRPCRouteMetadata) { + *out = *in + if in.Match != nil { + in, out := &in.Match, &out.Match + *out = new(GRPCRouteMetadataMatchMethod) + (*in).DeepCopyInto(*out) + } + if in.Invert != nil { + in, out := &in.Invert, &out.Invert + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteMetadata. +func (in *GRPCRouteMetadata) DeepCopy() *GRPCRouteMetadata { + if in == nil { + return nil + } + out := new(GRPCRouteMetadata) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCRouteMetadataMatchMethod) DeepCopyInto(out *GRPCRouteMetadataMatchMethod) { + *out = *in + if in.Exact != nil { + in, out := &in.Exact, &out.Exact + *out = new(string) + **out = **in + } + if in.Prefix != nil { + in, out := &in.Prefix, &out.Prefix + *out = new(string) + **out = **in + } + if in.Range != nil { + in, out := &in.Range, &out.Range + *out = new(MatchRange) + **out = **in + } + if in.Regex != nil { + in, out := &in.Regex, &out.Regex + *out = new(string) + **out = **in + } + if in.Suffix != nil { + in, out := &in.Suffix, &out.Suffix + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteMetadataMatchMethod. +func (in *GRPCRouteMetadataMatchMethod) DeepCopy() *GRPCRouteMetadataMatchMethod { + if in == nil { + return nil + } + out := new(GRPCRouteMetadataMatchMethod) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRetryPolicy) DeepCopyInto(out *HTTPRetryPolicy) { + *out = *in + if in.HTTPRetryEvents != nil { + in, out := &in.HTTPRetryEvents, &out.HTTPRetryEvents + *out = make([]HTTPRetryPolicyEvent, len(*in)) + copy(*out, *in) + } + if in.TCPRetryEvents != nil { + in, out := &in.TCPRetryEvents, &out.TCPRetryEvents + *out = make([]TCPRetryPolicyEvent, len(*in)) + copy(*out, *in) + } + out.PerRetryTimeout = in.PerRetryTimeout + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRetryPolicy. +func (in *HTTPRetryPolicy) DeepCopy() *HTTPRetryPolicy { + if in == nil { + return nil + } + out := new(HTTPRetryPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { + *out = *in + in.Match.DeepCopyInto(&out.Match) + in.Action.DeepCopyInto(&out.Action) + if in.RetryPolicy != nil { + in, out := &in.RetryPolicy, &out.RetryPolicy + *out = new(HTTPRetryPolicy) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. +func (in *HTTPRoute) DeepCopy() *HTTPRoute { + if in == nil { + return nil + } + out := new(HTTPRoute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteAction) DeepCopyInto(out *HTTPRouteAction) { + *out = *in + if in.WeightedTargets != nil { + in, out := &in.WeightedTargets, &out.WeightedTargets + *out = make([]WeightedTarget, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteAction. +func (in *HTTPRouteAction) DeepCopy() *HTTPRouteAction { + if in == nil { + return nil + } + out := new(HTTPRouteAction) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteHeader) DeepCopyInto(out *HTTPRouteHeader) { + *out = *in + if in.Match != nil { + in, out := &in.Match, &out.Match + *out = new(HeaderMatchMethod) + (*in).DeepCopyInto(*out) + } + if in.Invert != nil { + in, out := &in.Invert, &out.Invert + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteHeader. +func (in *HTTPRouteHeader) DeepCopy() *HTTPRouteHeader { + if in == nil { + return nil + } + out := new(HTTPRouteHeader) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteMatch) DeepCopyInto(out *HTTPRouteMatch) { + *out = *in + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]HTTPRouteHeader, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Method != nil { + in, out := &in.Method, &out.Method + *out = new(string) + **out = **in + } + if in.Scheme != nil { + in, out := &in.Scheme, &out.Scheme + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteMatch. +func (in *HTTPRouteMatch) DeepCopy() *HTTPRouteMatch { + if in == nil { + return nil + } + out := new(HTTPRouteMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HeaderMatchMethod) DeepCopyInto(out *HeaderMatchMethod) { + *out = *in + if in.Exact != nil { + in, out := &in.Exact, &out.Exact + *out = new(string) + **out = **in + } + if in.Prefix != nil { + in, out := &in.Prefix, &out.Prefix + *out = new(string) + **out = **in + } + if in.Range != nil { + in, out := &in.Range, &out.Range + *out = new(MatchRange) + **out = **in + } + if in.Regex != nil { + in, out := &in.Regex, &out.Regex + *out = new(string) + **out = **in + } + if in.Suffix != nil { + in, out := &in.Suffix, &out.Suffix + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderMatchMethod. +func (in *HeaderMatchMethod) DeepCopy() *HeaderMatchMethod { + if in == nil { + return nil + } + out := new(HeaderMatchMethod) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HealthCheckPolicy) DeepCopyInto(out *HealthCheckPolicy) { + *out = *in + if in.HealthyThreshold != nil { + in, out := &in.HealthyThreshold, &out.HealthyThreshold + *out = new(int64) + **out = **in + } + if in.IntervalMillis != nil { + in, out := &in.IntervalMillis, &out.IntervalMillis + *out = new(int64) + **out = **in + } + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(string) + **out = **in + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(PortNumber) + **out = **in + } + if in.Protocol != nil { + in, out := &in.Protocol, &out.Protocol + *out = new(PortProtocol) + **out = **in + } + if in.TimeoutMillis != nil { + in, out := &in.TimeoutMillis, &out.TimeoutMillis + *out = new(int64) + **out = **in + } + if in.UnhealthyThreshold != nil { + in, out := &in.UnhealthyThreshold, &out.UnhealthyThreshold + *out = new(int64) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheckPolicy. +func (in *HealthCheckPolicy) DeepCopy() *HealthCheckPolicy { + if in == nil { + return nil + } + out := new(HealthCheckPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Listener) DeepCopyInto(out *Listener) { + *out = *in + out.PortMapping = in.PortMapping + if in.HealthCheck != nil { + in, out := &in.HealthCheck, &out.HealthCheck + *out = new(HealthCheckPolicy) + (*in).DeepCopyInto(*out) + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(ListenerTLS) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Listener. +func (in *Listener) DeepCopy() *Listener { + if in == nil { + return nil + } + out := new(Listener) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerTLS) DeepCopyInto(out *ListenerTLS) { + *out = *in + in.Certificate.DeepCopyInto(&out.Certificate) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerTLS. +func (in *ListenerTLS) DeepCopy() *ListenerTLS { + if in == nil { + return nil + } + out := new(ListenerTLS) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerTLSACMCertificate) DeepCopyInto(out *ListenerTLSACMCertificate) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerTLSACMCertificate. +func (in *ListenerTLSACMCertificate) DeepCopy() *ListenerTLSACMCertificate { + if in == nil { + return nil + } + out := new(ListenerTLSACMCertificate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerTLSCertificate) DeepCopyInto(out *ListenerTLSCertificate) { + *out = *in + if in.ACM != nil { + in, out := &in.ACM, &out.ACM + *out = new(ListenerTLSACMCertificate) + **out = **in + } + if in.File != nil { + in, out := &in.File, &out.File + *out = new(ListenerTLSFileCertificate) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerTLSCertificate. +func (in *ListenerTLSCertificate) DeepCopy() *ListenerTLSCertificate { + if in == nil { + return nil + } + out := new(ListenerTLSCertificate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerTLSFileCertificate) DeepCopyInto(out *ListenerTLSFileCertificate) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerTLSFileCertificate. +func (in *ListenerTLSFileCertificate) DeepCopy() *ListenerTLSFileCertificate { + if in == nil { + return nil + } + out := new(ListenerTLSFileCertificate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Logging) DeepCopyInto(out *Logging) { + *out = *in + if in.AccessLog != nil { + in, out := &in.AccessLog, &out.AccessLog + *out = new(AccessLog) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Logging. +func (in *Logging) DeepCopy() *Logging { + if in == nil { + return nil + } + out := new(Logging) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MatchRange) DeepCopyInto(out *MatchRange) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchRange. +func (in *MatchRange) DeepCopy() *MatchRange { + if in == nil { + return nil + } + out := new(MatchRange) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshReference) DeepCopyInto(out *MeshReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshReference. +func (in *MeshReference) DeepCopy() *MeshReference { + if in == nil { + return nil + } + out := new(MeshReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PortMapping) DeepCopyInto(out *PortMapping) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortMapping. +func (in *PortMapping) DeepCopy() *PortMapping { + if in == nil { + return nil + } + out := new(PortMapping) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Route) DeepCopyInto(out *Route) { + *out = *in + if in.GRPCRoute != nil { + in, out := &in.GRPCRoute, &out.GRPCRoute + *out = new(GRPCRoute) + (*in).DeepCopyInto(*out) + } + if in.HTTPRoute != nil { + in, out := &in.HTTPRoute, &out.HTTPRoute + *out = new(HTTPRoute) + (*in).DeepCopyInto(*out) + } + if in.HTTP2Route != nil { + in, out := &in.HTTP2Route, &out.HTTP2Route + *out = new(HTTPRoute) + (*in).DeepCopyInto(*out) + } + if in.TCPRoute != nil { + in, out := &in.TCPRoute, &out.TCPRoute + *out = new(TCPRoute) + (*in).DeepCopyInto(*out) + } + if in.Priority != nil { + in, out := &in.Priority, &out.Priority + *out = new(int64) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Route. +func (in *Route) DeepCopy() *Route { + if in == nil { + return nil + } + out := new(Route) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceDiscovery) DeepCopyInto(out *ServiceDiscovery) { + *out = *in + if in.AWSCloudMap != nil { + in, out := &in.AWSCloudMap, &out.AWSCloudMap + *out = new(AWSCloudMapServiceDiscovery) + (*in).DeepCopyInto(*out) + } + if in.DNS != nil { + in, out := &in.DNS, &out.DNS + *out = new(DNSServiceDiscovery) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceDiscovery. +func (in *ServiceDiscovery) DeepCopy() *ServiceDiscovery { + if in == nil { + return nil + } + out := new(ServiceDiscovery) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPRoute) DeepCopyInto(out *TCPRoute) { + *out = *in + in.Action.DeepCopyInto(&out.Action) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPRoute. +func (in *TCPRoute) DeepCopy() *TCPRoute { + if in == nil { + return nil + } + out := new(TCPRoute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPRouteAction) DeepCopyInto(out *TCPRouteAction) { + *out = *in + if in.WeightedTargets != nil { + in, out := &in.WeightedTargets, &out.WeightedTargets + *out = make([]WeightedTarget, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPRouteAction. +func (in *TCPRouteAction) DeepCopy() *TCPRouteAction { + if in == nil { + return nil + } + out := new(TCPRouteAction) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSValidationContext) DeepCopyInto(out *TLSValidationContext) { + *out = *in + in.Trust.DeepCopyInto(&out.Trust) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSValidationContext. +func (in *TLSValidationContext) DeepCopy() *TLSValidationContext { + if in == nil { + return nil + } + out := new(TLSValidationContext) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSValidationContextACMTrust) DeepCopyInto(out *TLSValidationContextACMTrust) { + *out = *in + if in.CertificateAuthorityARNs != nil { + in, out := &in.CertificateAuthorityARNs, &out.CertificateAuthorityARNs + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSValidationContextACMTrust. +func (in *TLSValidationContextACMTrust) DeepCopy() *TLSValidationContextACMTrust { + if in == nil { + return nil + } + out := new(TLSValidationContextACMTrust) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSValidationContextFileTrust) DeepCopyInto(out *TLSValidationContextFileTrust) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSValidationContextFileTrust. +func (in *TLSValidationContextFileTrust) DeepCopy() *TLSValidationContextFileTrust { + if in == nil { + return nil + } + out := new(TLSValidationContextFileTrust) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSValidationContextTrust) DeepCopyInto(out *TLSValidationContextTrust) { + *out = *in + if in.ACM != nil { + in, out := &in.ACM, &out.ACM + *out = new(TLSValidationContextACMTrust) + (*in).DeepCopyInto(*out) + } + if in.File != nil { + in, out := &in.File, &out.File + *out = new(TLSValidationContextFileTrust) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSValidationContextTrust. +func (in *TLSValidationContextTrust) DeepCopy() *TLSValidationContextTrust { + if in == nil { + return nil + } + out := new(TLSValidationContextTrust) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualGatewayReference) DeepCopyInto(out *VirtualGatewayReference) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualGatewayReference. +func (in *VirtualGatewayReference) DeepCopy() *VirtualGatewayReference { + if in == nil { + return nil + } + out := new(VirtualGatewayReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNode) DeepCopyInto(out *VirtualNode) { + *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 VirtualNode. +func (in *VirtualNode) DeepCopy() *VirtualNode { + if in == nil { + return nil + } + out := new(VirtualNode) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualNode) 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 *VirtualNodeCondition) DeepCopyInto(out *VirtualNodeCondition) { + *out = *in + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } + if in.Reason != nil { + in, out := &in.Reason, &out.Reason + *out = new(string) + **out = **in + } + if in.Message != nil { + in, out := &in.Message, &out.Message + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNodeCondition. +func (in *VirtualNodeCondition) DeepCopy() *VirtualNodeCondition { + if in == nil { + return nil + } + out := new(VirtualNodeCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNodeList) DeepCopyInto(out *VirtualNodeList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualNode, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNodeList. +func (in *VirtualNodeList) DeepCopy() *VirtualNodeList { + if in == nil { + return nil + } + out := new(VirtualNodeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualNodeList) 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 *VirtualNodeReference) DeepCopyInto(out *VirtualNodeReference) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNodeReference. +func (in *VirtualNodeReference) DeepCopy() *VirtualNodeReference { + if in == nil { + return nil + } + out := new(VirtualNodeReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNodeServiceProvider) DeepCopyInto(out *VirtualNodeServiceProvider) { + *out = *in + in.VirtualNodeRef.DeepCopyInto(&out.VirtualNodeRef) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNodeServiceProvider. +func (in *VirtualNodeServiceProvider) DeepCopy() *VirtualNodeServiceProvider { + if in == nil { + return nil + } + out := new(VirtualNodeServiceProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNodeSpec) DeepCopyInto(out *VirtualNodeSpec) { + *out = *in + if in.AWSName != nil { + in, out := &in.AWSName, &out.AWSName + *out = new(string) + **out = **in + } + if in.PodSelector != nil { + in, out := &in.PodSelector, &out.PodSelector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.Listeners != nil { + in, out := &in.Listeners, &out.Listeners + *out = make([]Listener, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ServiceDiscovery != nil { + in, out := &in.ServiceDiscovery, &out.ServiceDiscovery + *out = new(ServiceDiscovery) + (*in).DeepCopyInto(*out) + } + if in.Backends != nil { + in, out := &in.Backends, &out.Backends + *out = make([]Backend, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.BackendDefaults != nil { + in, out := &in.BackendDefaults, &out.BackendDefaults + *out = new(BackendDefaults) + (*in).DeepCopyInto(*out) + } + if in.Logging != nil { + in, out := &in.Logging, &out.Logging + *out = new(Logging) + (*in).DeepCopyInto(*out) + } + if in.MeshRef != nil { + in, out := &in.MeshRef, &out.MeshRef + *out = new(MeshReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNodeSpec. +func (in *VirtualNodeSpec) DeepCopy() *VirtualNodeSpec { + if in == nil { + return nil + } + out := new(VirtualNodeSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNodeStatus) DeepCopyInto(out *VirtualNodeStatus) { + *out = *in + if in.VirtualNodeARN != nil { + in, out := &in.VirtualNodeARN, &out.VirtualNodeARN + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VirtualNodeCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AWSCloudMapServiceStatus != nil { + in, out := &in.AWSCloudMapServiceStatus, &out.AWSCloudMapServiceStatus + *out = new(AWSCloudMapServiceStatus) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNodeStatus. +func (in *VirtualNodeStatus) DeepCopy() *VirtualNodeStatus { + if in == nil { + return nil + } + out := new(VirtualNodeStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualRouter) DeepCopyInto(out *VirtualRouter) { + *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 VirtualRouter. +func (in *VirtualRouter) DeepCopy() *VirtualRouter { + if in == nil { + return nil + } + out := new(VirtualRouter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualRouter) 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 *VirtualRouterCondition) DeepCopyInto(out *VirtualRouterCondition) { + *out = *in + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } + if in.Reason != nil { + in, out := &in.Reason, &out.Reason + *out = new(string) + **out = **in + } + if in.Message != nil { + in, out := &in.Message, &out.Message + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualRouterCondition. +func (in *VirtualRouterCondition) DeepCopy() *VirtualRouterCondition { + if in == nil { + return nil + } + out := new(VirtualRouterCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualRouterList) DeepCopyInto(out *VirtualRouterList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualRouter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualRouterList. +func (in *VirtualRouterList) DeepCopy() *VirtualRouterList { + if in == nil { + return nil + } + out := new(VirtualRouterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualRouterList) 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 *VirtualRouterListener) DeepCopyInto(out *VirtualRouterListener) { + *out = *in + out.PortMapping = in.PortMapping + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualRouterListener. +func (in *VirtualRouterListener) DeepCopy() *VirtualRouterListener { + if in == nil { + return nil + } + out := new(VirtualRouterListener) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualRouterReference) DeepCopyInto(out *VirtualRouterReference) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualRouterReference. +func (in *VirtualRouterReference) DeepCopy() *VirtualRouterReference { + if in == nil { + return nil + } + out := new(VirtualRouterReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualRouterServiceProvider) DeepCopyInto(out *VirtualRouterServiceProvider) { + *out = *in + in.VirtualRouterRef.DeepCopyInto(&out.VirtualRouterRef) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualRouterServiceProvider. +func (in *VirtualRouterServiceProvider) DeepCopy() *VirtualRouterServiceProvider { + if in == nil { + return nil + } + out := new(VirtualRouterServiceProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualRouterSpec) DeepCopyInto(out *VirtualRouterSpec) { + *out = *in + if in.AWSName != nil { + in, out := &in.AWSName, &out.AWSName + *out = new(string) + **out = **in + } + if in.Listeners != nil { + in, out := &in.Listeners, &out.Listeners + *out = make([]VirtualRouterListener, len(*in)) + copy(*out, *in) + } + if in.Routes != nil { + in, out := &in.Routes, &out.Routes + *out = make([]Route, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.MeshRef != nil { + in, out := &in.MeshRef, &out.MeshRef + *out = new(MeshReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualRouterSpec. +func (in *VirtualRouterSpec) DeepCopy() *VirtualRouterSpec { + if in == nil { + return nil + } + out := new(VirtualRouterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualRouterStatus) DeepCopyInto(out *VirtualRouterStatus) { + *out = *in + if in.VirtualRouterARN != nil { + in, out := &in.VirtualRouterARN, &out.VirtualRouterARN + *out = new(string) + **out = **in + } + if in.RouteARNs != nil { + in, out := &in.RouteARNs, &out.RouteARNs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VirtualRouterCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualRouterStatus. +func (in *VirtualRouterStatus) DeepCopy() *VirtualRouterStatus { + if in == nil { + return nil + } + out := new(VirtualRouterStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualService) DeepCopyInto(out *VirtualService) { + *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 VirtualService. +func (in *VirtualService) DeepCopy() *VirtualService { + if in == nil { + return nil + } + out := new(VirtualService) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualService) 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 *VirtualServiceBackend) DeepCopyInto(out *VirtualServiceBackend) { + *out = *in + in.VirtualServiceRef.DeepCopyInto(&out.VirtualServiceRef) + if in.ClientPolicy != nil { + in, out := &in.ClientPolicy, &out.ClientPolicy + *out = new(ClientPolicy) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceBackend. +func (in *VirtualServiceBackend) DeepCopy() *VirtualServiceBackend { + if in == nil { + return nil + } + out := new(VirtualServiceBackend) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualServiceCondition) DeepCopyInto(out *VirtualServiceCondition) { + *out = *in + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } + if in.Reason != nil { + in, out := &in.Reason, &out.Reason + *out = new(string) + **out = **in + } + if in.Message != nil { + in, out := &in.Message, &out.Message + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceCondition. +func (in *VirtualServiceCondition) DeepCopy() *VirtualServiceCondition { + if in == nil { + return nil + } + out := new(VirtualServiceCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualServiceList) DeepCopyInto(out *VirtualServiceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VirtualService, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceList. +func (in *VirtualServiceList) DeepCopy() *VirtualServiceList { + if in == nil { + return nil + } + out := new(VirtualServiceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VirtualServiceList) 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 *VirtualServiceProvider) DeepCopyInto(out *VirtualServiceProvider) { + *out = *in + if in.VirtualNode != nil { + in, out := &in.VirtualNode, &out.VirtualNode + *out = new(VirtualNodeServiceProvider) + (*in).DeepCopyInto(*out) + } + if in.VirtualRouter != nil { + in, out := &in.VirtualRouter, &out.VirtualRouter + *out = new(VirtualRouterServiceProvider) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceProvider. +func (in *VirtualServiceProvider) DeepCopy() *VirtualServiceProvider { + if in == nil { + return nil + } + out := new(VirtualServiceProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualServiceReference) DeepCopyInto(out *VirtualServiceReference) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceReference. +func (in *VirtualServiceReference) DeepCopy() *VirtualServiceReference { + if in == nil { + return nil + } + out := new(VirtualServiceReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualServiceSpec) DeepCopyInto(out *VirtualServiceSpec) { + *out = *in + if in.AWSName != nil { + in, out := &in.AWSName, &out.AWSName + *out = new(string) + **out = **in + } + if in.Provider != nil { + in, out := &in.Provider, &out.Provider + *out = new(VirtualServiceProvider) + (*in).DeepCopyInto(*out) + } + if in.MeshRef != nil { + in, out := &in.MeshRef, &out.MeshRef + *out = new(MeshReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceSpec. +func (in *VirtualServiceSpec) DeepCopy() *VirtualServiceSpec { + if in == nil { + return nil + } + out := new(VirtualServiceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualServiceStatus) DeepCopyInto(out *VirtualServiceStatus) { + *out = *in + if in.VirtualServiceARN != nil { + in, out := &in.VirtualServiceARN, &out.VirtualServiceARN + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VirtualServiceCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceStatus. +func (in *VirtualServiceStatus) DeepCopy() *VirtualServiceStatus { + if in == nil { + return nil + } + out := new(VirtualServiceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WeightedTarget) DeepCopyInto(out *WeightedTarget) { + *out = *in + in.VirtualNodeRef.DeepCopyInto(&out.VirtualNodeRef) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WeightedTarget. +func (in *WeightedTarget) DeepCopy() *WeightedTarget { + if in == nil { + return nil + } + out := new(WeightedTarget) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apis/flagger/v1beta1/provider.go b/pkg/apis/flagger/v1beta1/provider.go new file mode 100644 index 000000000..9dbcf0174 --- /dev/null +++ b/pkg/apis/flagger/v1beta1/provider.go @@ -0,0 +1,12 @@ +package v1beta1 + +const ( + AppMeshProvider string = "appmesh" + LinkerdProvider string = "linkerd" + IstioProvider string = "istio" + SMIProvider string = "smi" + ContourProvider string = "contour" + GlooProvider string = "gloo" + NGINXProvider string = "nginx" + KubernetesProvider string = "kubernetes" +) diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index b6b73b421..fc0b22c30 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -22,6 +22,7 @@ import ( "fmt" appmeshv1beta1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/appmesh/v1beta1" + appmeshv1beta2 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/appmesh/v1beta2" flaggerv1beta1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/flagger/v1beta1" gloov1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/gloo/v1" networkingv1alpha3 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3" @@ -35,6 +36,7 @@ import ( type Interface interface { Discovery() discovery.DiscoveryInterface + AppmeshV1beta2() appmeshv1beta2.AppmeshV1beta2Interface AppmeshV1beta1() appmeshv1beta1.AppmeshV1beta1Interface FlaggerV1beta1() flaggerv1beta1.FlaggerV1beta1Interface GlooV1() gloov1.GlooV1Interface @@ -48,6 +50,7 @@ type Interface interface { // version included in a Clientset. type Clientset struct { *discovery.DiscoveryClient + appmeshV1beta2 *appmeshv1beta2.AppmeshV1beta2Client appmeshV1beta1 *appmeshv1beta1.AppmeshV1beta1Client flaggerV1beta1 *flaggerv1beta1.FlaggerV1beta1Client glooV1 *gloov1.GlooV1Client @@ -57,6 +60,11 @@ type Clientset struct { splitV1alpha2 *splitv1alpha2.SplitV1alpha2Client } +// AppmeshV1beta2 retrieves the AppmeshV1beta2Client +func (c *Clientset) AppmeshV1beta2() appmeshv1beta2.AppmeshV1beta2Interface { + return c.appmeshV1beta2 +} + // AppmeshV1beta1 retrieves the AppmeshV1beta1Client func (c *Clientset) AppmeshV1beta1() appmeshv1beta1.AppmeshV1beta1Interface { return c.appmeshV1beta1 @@ -113,6 +121,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { } var cs Clientset var err error + cs.appmeshV1beta2, err = appmeshv1beta2.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.appmeshV1beta1, err = appmeshv1beta1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -153,6 +165,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset + cs.appmeshV1beta2 = appmeshv1beta2.NewForConfigOrDie(c) cs.appmeshV1beta1 = appmeshv1beta1.NewForConfigOrDie(c) cs.flaggerV1beta1 = flaggerv1beta1.NewForConfigOrDie(c) cs.glooV1 = gloov1.NewForConfigOrDie(c) @@ -168,6 +181,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { // New creates a new Clientset for the given RESTClient. func New(c rest.Interface) *Clientset { var cs Clientset + cs.appmeshV1beta2 = appmeshv1beta2.New(c) cs.appmeshV1beta1 = appmeshv1beta1.New(c) cs.flaggerV1beta1 = flaggerv1beta1.New(c) cs.glooV1 = gloov1.New(c) diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index bf7600125..d68d11428 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -22,6 +22,8 @@ import ( clientset "github.com/weaveworks/flagger/pkg/client/clientset/versioned" appmeshv1beta1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/appmesh/v1beta1" fakeappmeshv1beta1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/appmesh/v1beta1/fake" + appmeshv1beta2 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/appmesh/v1beta2" + fakeappmeshv1beta2 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake" flaggerv1beta1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/flagger/v1beta1" fakeflaggerv1beta1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/flagger/v1beta1/fake" gloov1 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/gloo/v1" @@ -88,6 +90,11 @@ func (c *Clientset) Tracker() testing.ObjectTracker { var _ clientset.Interface = &Clientset{} +// AppmeshV1beta2 retrieves the AppmeshV1beta2Client +func (c *Clientset) AppmeshV1beta2() appmeshv1beta2.AppmeshV1beta2Interface { + return &fakeappmeshv1beta2.FakeAppmeshV1beta2{Fake: &c.Fake} +} + // AppmeshV1beta1 retrieves the AppmeshV1beta1Client func (c *Clientset) AppmeshV1beta1() appmeshv1beta1.AppmeshV1beta1Interface { return &fakeappmeshv1beta1.FakeAppmeshV1beta1{Fake: &c.Fake} diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index 07d2d1823..e5ab88c5e 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -20,6 +20,7 @@ package fake import ( appmeshv1beta1 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta1" + appmeshv1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" flaggerv1beta1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" gloov1 "github.com/weaveworks/flagger/pkg/apis/gloo/v1" networkingv1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3" @@ -37,6 +38,7 @@ var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) var parameterCodec = runtime.NewParameterCodec(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ + appmeshv1beta2.AddToScheme, appmeshv1beta1.AddToScheme, flaggerv1beta1.AddToScheme, gloov1.AddToScheme, diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index d27b9397a..19b1677cf 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -20,6 +20,7 @@ package scheme import ( appmeshv1beta1 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta1" + appmeshv1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" flaggerv1beta1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" gloov1 "github.com/weaveworks/flagger/pkg/apis/gloo/v1" networkingv1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3" @@ -37,6 +38,7 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ + appmeshv1beta2.AddToScheme, appmeshv1beta1.AddToScheme, flaggerv1beta1.AddToScheme, gloov1.AddToScheme, diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/appmesh_client.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/appmesh_client.go new file mode 100644 index 000000000..4af19f9fc --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/appmesh_client.go @@ -0,0 +1,99 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + "github.com/weaveworks/flagger/pkg/client/clientset/versioned/scheme" + rest "k8s.io/client-go/rest" +) + +type AppmeshV1beta2Interface interface { + RESTClient() rest.Interface + VirtualNodesGetter + VirtualRoutersGetter + VirtualServicesGetter +} + +// AppmeshV1beta2Client is used to interact with features provided by the appmesh.k8s.aws group. +type AppmeshV1beta2Client struct { + restClient rest.Interface +} + +func (c *AppmeshV1beta2Client) VirtualNodes(namespace string) VirtualNodeInterface { + return newVirtualNodes(c, namespace) +} + +func (c *AppmeshV1beta2Client) VirtualRouters(namespace string) VirtualRouterInterface { + return newVirtualRouters(c, namespace) +} + +func (c *AppmeshV1beta2Client) VirtualServices(namespace string) VirtualServiceInterface { + return newVirtualServices(c, namespace) +} + +// NewForConfig creates a new AppmeshV1beta2Client for the given config. +func NewForConfig(c *rest.Config) (*AppmeshV1beta2Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &AppmeshV1beta2Client{client}, nil +} + +// NewForConfigOrDie creates a new AppmeshV1beta2Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *AppmeshV1beta2Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new AppmeshV1beta2Client for the given RESTClient. +func New(c rest.Interface) *AppmeshV1beta2Client { + return &AppmeshV1beta2Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1beta2.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 *AppmeshV1beta2Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/doc.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/doc.go new file mode 100644 index 000000000..a36957cda --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Flagger 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 v1beta2 diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/doc.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/doc.go new file mode 100644 index 000000000..7a3b19cb7 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Flagger 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/appmesh/v1beta2/fake/fake_appmesh_client.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_appmesh_client.go new file mode 100644 index 000000000..ad03bad89 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_appmesh_client.go @@ -0,0 +1,48 @@ +/* +Copyright The Flagger 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 ( + v1beta2 "github.com/weaveworks/flagger/pkg/client/clientset/versioned/typed/appmesh/v1beta2" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeAppmeshV1beta2 struct { + *testing.Fake +} + +func (c *FakeAppmeshV1beta2) VirtualNodes(namespace string) v1beta2.VirtualNodeInterface { + return &FakeVirtualNodes{c, namespace} +} + +func (c *FakeAppmeshV1beta2) VirtualRouters(namespace string) v1beta2.VirtualRouterInterface { + return &FakeVirtualRouters{c, namespace} +} + +func (c *FakeAppmeshV1beta2) VirtualServices(namespace string) v1beta2.VirtualServiceInterface { + return &FakeVirtualServices{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeAppmeshV1beta2) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_virtualnode.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_virtualnode.go new file mode 100644 index 000000000..96d63230e --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_virtualnode.go @@ -0,0 +1,142 @@ +/* +Copyright The Flagger 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" + + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeVirtualNodes implements VirtualNodeInterface +type FakeVirtualNodes struct { + Fake *FakeAppmeshV1beta2 + ns string +} + +var virtualnodesResource = schema.GroupVersionResource{Group: "appmesh.k8s.aws", Version: "v1beta2", Resource: "virtualnodes"} + +var virtualnodesKind = schema.GroupVersionKind{Group: "appmesh.k8s.aws", Version: "v1beta2", Kind: "VirtualNode"} + +// Get takes name of the virtualNode, and returns the corresponding virtualNode object, and an error if there is any. +func (c *FakeVirtualNodes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.VirtualNode, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(virtualnodesResource, c.ns, name), &v1beta2.VirtualNode{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualNode), err +} + +// List takes label and field selectors, and returns the list of VirtualNodes that match those selectors. +func (c *FakeVirtualNodes) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.VirtualNodeList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(virtualnodesResource, virtualnodesKind, c.ns, opts), &v1beta2.VirtualNodeList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta2.VirtualNodeList{ListMeta: obj.(*v1beta2.VirtualNodeList).ListMeta} + for _, item := range obj.(*v1beta2.VirtualNodeList).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 virtualNodes. +func (c *FakeVirtualNodes) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(virtualnodesResource, c.ns, opts)) + +} + +// Create takes the representation of a virtualNode and creates it. Returns the server's representation of the virtualNode, and an error, if there is any. +func (c *FakeVirtualNodes) Create(ctx context.Context, virtualNode *v1beta2.VirtualNode, opts v1.CreateOptions) (result *v1beta2.VirtualNode, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(virtualnodesResource, c.ns, virtualNode), &v1beta2.VirtualNode{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualNode), err +} + +// Update takes the representation of a virtualNode and updates it. Returns the server's representation of the virtualNode, and an error, if there is any. +func (c *FakeVirtualNodes) Update(ctx context.Context, virtualNode *v1beta2.VirtualNode, opts v1.UpdateOptions) (result *v1beta2.VirtualNode, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(virtualnodesResource, c.ns, virtualNode), &v1beta2.VirtualNode{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualNode), 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 *FakeVirtualNodes) UpdateStatus(ctx context.Context, virtualNode *v1beta2.VirtualNode, opts v1.UpdateOptions) (*v1beta2.VirtualNode, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(virtualnodesResource, "status", c.ns, virtualNode), &v1beta2.VirtualNode{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualNode), err +} + +// Delete takes name of the virtualNode and deletes it. Returns an error if one occurs. +func (c *FakeVirtualNodes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(virtualnodesResource, c.ns, name), &v1beta2.VirtualNode{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeVirtualNodes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(virtualnodesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1beta2.VirtualNodeList{}) + return err +} + +// Patch applies the patch and returns the patched virtualNode. +func (c *FakeVirtualNodes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.VirtualNode, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(virtualnodesResource, c.ns, name, pt, data, subresources...), &v1beta2.VirtualNode{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualNode), err +} diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_virtualrouter.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_virtualrouter.go new file mode 100644 index 000000000..faf658da7 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_virtualrouter.go @@ -0,0 +1,142 @@ +/* +Copyright The Flagger 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" + + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeVirtualRouters implements VirtualRouterInterface +type FakeVirtualRouters struct { + Fake *FakeAppmeshV1beta2 + ns string +} + +var virtualroutersResource = schema.GroupVersionResource{Group: "appmesh.k8s.aws", Version: "v1beta2", Resource: "virtualrouters"} + +var virtualroutersKind = schema.GroupVersionKind{Group: "appmesh.k8s.aws", Version: "v1beta2", Kind: "VirtualRouter"} + +// Get takes name of the virtualRouter, and returns the corresponding virtualRouter object, and an error if there is any. +func (c *FakeVirtualRouters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.VirtualRouter, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(virtualroutersResource, c.ns, name), &v1beta2.VirtualRouter{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualRouter), err +} + +// List takes label and field selectors, and returns the list of VirtualRouters that match those selectors. +func (c *FakeVirtualRouters) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.VirtualRouterList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(virtualroutersResource, virtualroutersKind, c.ns, opts), &v1beta2.VirtualRouterList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta2.VirtualRouterList{ListMeta: obj.(*v1beta2.VirtualRouterList).ListMeta} + for _, item := range obj.(*v1beta2.VirtualRouterList).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 virtualRouters. +func (c *FakeVirtualRouters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(virtualroutersResource, c.ns, opts)) + +} + +// Create takes the representation of a virtualRouter and creates it. Returns the server's representation of the virtualRouter, and an error, if there is any. +func (c *FakeVirtualRouters) Create(ctx context.Context, virtualRouter *v1beta2.VirtualRouter, opts v1.CreateOptions) (result *v1beta2.VirtualRouter, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(virtualroutersResource, c.ns, virtualRouter), &v1beta2.VirtualRouter{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualRouter), err +} + +// Update takes the representation of a virtualRouter and updates it. Returns the server's representation of the virtualRouter, and an error, if there is any. +func (c *FakeVirtualRouters) Update(ctx context.Context, virtualRouter *v1beta2.VirtualRouter, opts v1.UpdateOptions) (result *v1beta2.VirtualRouter, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(virtualroutersResource, c.ns, virtualRouter), &v1beta2.VirtualRouter{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualRouter), 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 *FakeVirtualRouters) UpdateStatus(ctx context.Context, virtualRouter *v1beta2.VirtualRouter, opts v1.UpdateOptions) (*v1beta2.VirtualRouter, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(virtualroutersResource, "status", c.ns, virtualRouter), &v1beta2.VirtualRouter{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualRouter), err +} + +// Delete takes name of the virtualRouter and deletes it. Returns an error if one occurs. +func (c *FakeVirtualRouters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(virtualroutersResource, c.ns, name), &v1beta2.VirtualRouter{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeVirtualRouters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(virtualroutersResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1beta2.VirtualRouterList{}) + return err +} + +// Patch applies the patch and returns the patched virtualRouter. +func (c *FakeVirtualRouters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.VirtualRouter, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(virtualroutersResource, c.ns, name, pt, data, subresources...), &v1beta2.VirtualRouter{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualRouter), err +} diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_virtualservice.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_virtualservice.go new file mode 100644 index 000000000..252039620 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/fake/fake_virtualservice.go @@ -0,0 +1,142 @@ +/* +Copyright The Flagger 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" + + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeVirtualServices implements VirtualServiceInterface +type FakeVirtualServices struct { + Fake *FakeAppmeshV1beta2 + ns string +} + +var virtualservicesResource = schema.GroupVersionResource{Group: "appmesh.k8s.aws", Version: "v1beta2", Resource: "virtualservices"} + +var virtualservicesKind = schema.GroupVersionKind{Group: "appmesh.k8s.aws", Version: "v1beta2", Kind: "VirtualService"} + +// Get takes name of the virtualService, and returns the corresponding virtualService object, and an error if there is any. +func (c *FakeVirtualServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.VirtualService, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(virtualservicesResource, c.ns, name), &v1beta2.VirtualService{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualService), err +} + +// List takes label and field selectors, and returns the list of VirtualServices that match those selectors. +func (c *FakeVirtualServices) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.VirtualServiceList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(virtualservicesResource, virtualservicesKind, c.ns, opts), &v1beta2.VirtualServiceList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta2.VirtualServiceList{ListMeta: obj.(*v1beta2.VirtualServiceList).ListMeta} + for _, item := range obj.(*v1beta2.VirtualServiceList).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 virtualServices. +func (c *FakeVirtualServices) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(virtualservicesResource, c.ns, opts)) + +} + +// Create takes the representation of a virtualService and creates it. Returns the server's representation of the virtualService, and an error, if there is any. +func (c *FakeVirtualServices) Create(ctx context.Context, virtualService *v1beta2.VirtualService, opts v1.CreateOptions) (result *v1beta2.VirtualService, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(virtualservicesResource, c.ns, virtualService), &v1beta2.VirtualService{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualService), err +} + +// Update takes the representation of a virtualService and updates it. Returns the server's representation of the virtualService, and an error, if there is any. +func (c *FakeVirtualServices) Update(ctx context.Context, virtualService *v1beta2.VirtualService, opts v1.UpdateOptions) (result *v1beta2.VirtualService, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(virtualservicesResource, c.ns, virtualService), &v1beta2.VirtualService{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualService), 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 *FakeVirtualServices) UpdateStatus(ctx context.Context, virtualService *v1beta2.VirtualService, opts v1.UpdateOptions) (*v1beta2.VirtualService, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(virtualservicesResource, "status", c.ns, virtualService), &v1beta2.VirtualService{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualService), err +} + +// Delete takes name of the virtualService and deletes it. Returns an error if one occurs. +func (c *FakeVirtualServices) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(virtualservicesResource, c.ns, name), &v1beta2.VirtualService{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeVirtualServices) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(virtualservicesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1beta2.VirtualServiceList{}) + return err +} + +// Patch applies the patch and returns the patched virtualService. +func (c *FakeVirtualServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.VirtualService, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(virtualservicesResource, c.ns, name, pt, data, subresources...), &v1beta2.VirtualService{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta2.VirtualService), err +} diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/generated_expansion.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/generated_expansion.go new file mode 100644 index 000000000..7803347c2 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/generated_expansion.go @@ -0,0 +1,25 @@ +/* +Copyright The Flagger 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 v1beta2 + +type VirtualNodeExpansion interface{} + +type VirtualRouterExpansion interface{} + +type VirtualServiceExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/virtualnode.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/virtualnode.go new file mode 100644 index 000000000..87fc7b3e0 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/virtualnode.go @@ -0,0 +1,195 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + "context" + "time" + + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + scheme "github.com/weaveworks/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" +) + +// VirtualNodesGetter has a method to return a VirtualNodeInterface. +// A group's client should implement this interface. +type VirtualNodesGetter interface { + VirtualNodes(namespace string) VirtualNodeInterface +} + +// VirtualNodeInterface has methods to work with VirtualNode resources. +type VirtualNodeInterface interface { + Create(ctx context.Context, virtualNode *v1beta2.VirtualNode, opts v1.CreateOptions) (*v1beta2.VirtualNode, error) + Update(ctx context.Context, virtualNode *v1beta2.VirtualNode, opts v1.UpdateOptions) (*v1beta2.VirtualNode, error) + UpdateStatus(ctx context.Context, virtualNode *v1beta2.VirtualNode, opts v1.UpdateOptions) (*v1beta2.VirtualNode, 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) (*v1beta2.VirtualNode, error) + List(ctx context.Context, opts v1.ListOptions) (*v1beta2.VirtualNodeList, 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 *v1beta2.VirtualNode, err error) + VirtualNodeExpansion +} + +// virtualNodes implements VirtualNodeInterface +type virtualNodes struct { + client rest.Interface + ns string +} + +// newVirtualNodes returns a VirtualNodes +func newVirtualNodes(c *AppmeshV1beta2Client, namespace string) *virtualNodes { + return &virtualNodes{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the virtualNode, and returns the corresponding virtualNode object, and an error if there is any. +func (c *virtualNodes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.VirtualNode, err error) { + result = &v1beta2.VirtualNode{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualnodes"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VirtualNodes that match those selectors. +func (c *virtualNodes) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.VirtualNodeList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1beta2.VirtualNodeList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualnodes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested virtualNodes. +func (c *virtualNodes) 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("virtualnodes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a virtualNode and creates it. Returns the server's representation of the virtualNode, and an error, if there is any. +func (c *virtualNodes) Create(ctx context.Context, virtualNode *v1beta2.VirtualNode, opts v1.CreateOptions) (result *v1beta2.VirtualNode, err error) { + result = &v1beta2.VirtualNode{} + err = c.client.Post(). + Namespace(c.ns). + Resource("virtualnodes"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualNode). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a virtualNode and updates it. Returns the server's representation of the virtualNode, and an error, if there is any. +func (c *virtualNodes) Update(ctx context.Context, virtualNode *v1beta2.VirtualNode, opts v1.UpdateOptions) (result *v1beta2.VirtualNode, err error) { + result = &v1beta2.VirtualNode{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualnodes"). + Name(virtualNode.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualNode). + 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 *virtualNodes) UpdateStatus(ctx context.Context, virtualNode *v1beta2.VirtualNode, opts v1.UpdateOptions) (result *v1beta2.VirtualNode, err error) { + result = &v1beta2.VirtualNode{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualnodes"). + Name(virtualNode.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualNode). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the virtualNode and deletes it. Returns an error if one occurs. +func (c *virtualNodes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("virtualnodes"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *virtualNodes) 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("virtualnodes"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched virtualNode. +func (c *virtualNodes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.VirtualNode, err error) { + result = &v1beta2.VirtualNode{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("virtualnodes"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/virtualrouter.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/virtualrouter.go new file mode 100644 index 000000000..283c2f5a3 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/virtualrouter.go @@ -0,0 +1,195 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + "context" + "time" + + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + scheme "github.com/weaveworks/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" +) + +// VirtualRoutersGetter has a method to return a VirtualRouterInterface. +// A group's client should implement this interface. +type VirtualRoutersGetter interface { + VirtualRouters(namespace string) VirtualRouterInterface +} + +// VirtualRouterInterface has methods to work with VirtualRouter resources. +type VirtualRouterInterface interface { + Create(ctx context.Context, virtualRouter *v1beta2.VirtualRouter, opts v1.CreateOptions) (*v1beta2.VirtualRouter, error) + Update(ctx context.Context, virtualRouter *v1beta2.VirtualRouter, opts v1.UpdateOptions) (*v1beta2.VirtualRouter, error) + UpdateStatus(ctx context.Context, virtualRouter *v1beta2.VirtualRouter, opts v1.UpdateOptions) (*v1beta2.VirtualRouter, 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) (*v1beta2.VirtualRouter, error) + List(ctx context.Context, opts v1.ListOptions) (*v1beta2.VirtualRouterList, 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 *v1beta2.VirtualRouter, err error) + VirtualRouterExpansion +} + +// virtualRouters implements VirtualRouterInterface +type virtualRouters struct { + client rest.Interface + ns string +} + +// newVirtualRouters returns a VirtualRouters +func newVirtualRouters(c *AppmeshV1beta2Client, namespace string) *virtualRouters { + return &virtualRouters{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the virtualRouter, and returns the corresponding virtualRouter object, and an error if there is any. +func (c *virtualRouters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.VirtualRouter, err error) { + result = &v1beta2.VirtualRouter{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualrouters"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VirtualRouters that match those selectors. +func (c *virtualRouters) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.VirtualRouterList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1beta2.VirtualRouterList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualrouters"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested virtualRouters. +func (c *virtualRouters) 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("virtualrouters"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a virtualRouter and creates it. Returns the server's representation of the virtualRouter, and an error, if there is any. +func (c *virtualRouters) Create(ctx context.Context, virtualRouter *v1beta2.VirtualRouter, opts v1.CreateOptions) (result *v1beta2.VirtualRouter, err error) { + result = &v1beta2.VirtualRouter{} + err = c.client.Post(). + Namespace(c.ns). + Resource("virtualrouters"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualRouter). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a virtualRouter and updates it. Returns the server's representation of the virtualRouter, and an error, if there is any. +func (c *virtualRouters) Update(ctx context.Context, virtualRouter *v1beta2.VirtualRouter, opts v1.UpdateOptions) (result *v1beta2.VirtualRouter, err error) { + result = &v1beta2.VirtualRouter{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualrouters"). + Name(virtualRouter.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualRouter). + 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 *virtualRouters) UpdateStatus(ctx context.Context, virtualRouter *v1beta2.VirtualRouter, opts v1.UpdateOptions) (result *v1beta2.VirtualRouter, err error) { + result = &v1beta2.VirtualRouter{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualrouters"). + Name(virtualRouter.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualRouter). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the virtualRouter and deletes it. Returns an error if one occurs. +func (c *virtualRouters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("virtualrouters"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *virtualRouters) 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("virtualrouters"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched virtualRouter. +func (c *virtualRouters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.VirtualRouter, err error) { + result = &v1beta2.VirtualRouter{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("virtualrouters"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/appmesh/v1beta2/virtualservice.go b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/virtualservice.go new file mode 100644 index 000000000..c1f7a81d8 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/appmesh/v1beta2/virtualservice.go @@ -0,0 +1,195 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + "context" + "time" + + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + scheme "github.com/weaveworks/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" +) + +// VirtualServicesGetter has a method to return a VirtualServiceInterface. +// A group's client should implement this interface. +type VirtualServicesGetter interface { + VirtualServices(namespace string) VirtualServiceInterface +} + +// VirtualServiceInterface has methods to work with VirtualService resources. +type VirtualServiceInterface interface { + Create(ctx context.Context, virtualService *v1beta2.VirtualService, opts v1.CreateOptions) (*v1beta2.VirtualService, error) + Update(ctx context.Context, virtualService *v1beta2.VirtualService, opts v1.UpdateOptions) (*v1beta2.VirtualService, error) + UpdateStatus(ctx context.Context, virtualService *v1beta2.VirtualService, opts v1.UpdateOptions) (*v1beta2.VirtualService, 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) (*v1beta2.VirtualService, error) + List(ctx context.Context, opts v1.ListOptions) (*v1beta2.VirtualServiceList, 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 *v1beta2.VirtualService, err error) + VirtualServiceExpansion +} + +// virtualServices implements VirtualServiceInterface +type virtualServices struct { + client rest.Interface + ns string +} + +// newVirtualServices returns a VirtualServices +func newVirtualServices(c *AppmeshV1beta2Client, namespace string) *virtualServices { + return &virtualServices{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the virtualService, and returns the corresponding virtualService object, and an error if there is any. +func (c *virtualServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.VirtualService, err error) { + result = &v1beta2.VirtualService{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualservices"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VirtualServices that match those selectors. +func (c *virtualServices) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.VirtualServiceList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1beta2.VirtualServiceList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("virtualservices"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested virtualServices. +func (c *virtualServices) 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("virtualservices"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a virtualService and creates it. Returns the server's representation of the virtualService, and an error, if there is any. +func (c *virtualServices) Create(ctx context.Context, virtualService *v1beta2.VirtualService, opts v1.CreateOptions) (result *v1beta2.VirtualService, err error) { + result = &v1beta2.VirtualService{} + err = c.client.Post(). + Namespace(c.ns). + Resource("virtualservices"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualService). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a virtualService and updates it. Returns the server's representation of the virtualService, and an error, if there is any. +func (c *virtualServices) Update(ctx context.Context, virtualService *v1beta2.VirtualService, opts v1.UpdateOptions) (result *v1beta2.VirtualService, err error) { + result = &v1beta2.VirtualService{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualservices"). + Name(virtualService.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualService). + 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 *virtualServices) UpdateStatus(ctx context.Context, virtualService *v1beta2.VirtualService, opts v1.UpdateOptions) (result *v1beta2.VirtualService, err error) { + result = &v1beta2.VirtualService{} + err = c.client.Put(). + Namespace(c.ns). + Resource("virtualservices"). + Name(virtualService.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(virtualService). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the virtualService and deletes it. Returns an error if one occurs. +func (c *virtualServices) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("virtualservices"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *virtualServices) 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("virtualservices"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched virtualService. +func (c *virtualServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.VirtualService, err error) { + result = &v1beta2.VirtualService{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("virtualservices"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/appmesh/interface.go b/pkg/client/informers/externalversions/appmesh/interface.go index 376f4361b..5fd4d1673 100644 --- a/pkg/client/informers/externalversions/appmesh/interface.go +++ b/pkg/client/informers/externalversions/appmesh/interface.go @@ -20,11 +20,14 @@ package appmesh import ( v1beta1 "github.com/weaveworks/flagger/pkg/client/informers/externalversions/appmesh/v1beta1" + v1beta2 "github.com/weaveworks/flagger/pkg/client/informers/externalversions/appmesh/v1beta2" internalinterfaces "github.com/weaveworks/flagger/pkg/client/informers/externalversions/internalinterfaces" ) // Interface provides access to each of this group's versions. type Interface interface { + // V1beta2 provides access to shared informers for resources in V1beta2. + V1beta2() v1beta2.Interface // V1beta1 provides access to shared informers for resources in V1beta1. V1beta1() v1beta1.Interface } @@ -40,6 +43,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// V1beta2 returns a new v1beta2.Interface. +func (g *group) V1beta2() v1beta2.Interface { + return v1beta2.New(g.factory, g.namespace, g.tweakListOptions) +} + // V1beta1 returns a new v1beta1.Interface. func (g *group) V1beta1() v1beta1.Interface { return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) diff --git a/pkg/client/informers/externalversions/appmesh/v1beta2/interface.go b/pkg/client/informers/externalversions/appmesh/v1beta2/interface.go new file mode 100644 index 000000000..abe451b11 --- /dev/null +++ b/pkg/client/informers/externalversions/appmesh/v1beta2/interface.go @@ -0,0 +1,59 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + internalinterfaces "github.com/weaveworks/flagger/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // VirtualNodes returns a VirtualNodeInformer. + VirtualNodes() VirtualNodeInformer + // VirtualRouters returns a VirtualRouterInformer. + VirtualRouters() VirtualRouterInformer + // VirtualServices returns a VirtualServiceInformer. + VirtualServices() VirtualServiceInformer +} + +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} +} + +// VirtualNodes returns a VirtualNodeInformer. +func (v *version) VirtualNodes() VirtualNodeInformer { + return &virtualNodeInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// VirtualRouters returns a VirtualRouterInformer. +func (v *version) VirtualRouters() VirtualRouterInformer { + return &virtualRouterInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// VirtualServices returns a VirtualServiceInformer. +func (v *version) VirtualServices() VirtualServiceInformer { + return &virtualServiceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/informers/externalversions/appmesh/v1beta2/virtualnode.go b/pkg/client/informers/externalversions/appmesh/v1beta2/virtualnode.go new file mode 100644 index 000000000..d84cf80ca --- /dev/null +++ b/pkg/client/informers/externalversions/appmesh/v1beta2/virtualnode.go @@ -0,0 +1,90 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + "context" + time "time" + + appmeshv1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + versioned "github.com/weaveworks/flagger/pkg/client/clientset/versioned" + internalinterfaces "github.com/weaveworks/flagger/pkg/client/informers/externalversions/internalinterfaces" + v1beta2 "github.com/weaveworks/flagger/pkg/client/listers/appmesh/v1beta2" + 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" +) + +// VirtualNodeInformer provides access to a shared informer and lister for +// VirtualNodes. +type VirtualNodeInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1beta2.VirtualNodeLister +} + +type virtualNodeInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewVirtualNodeInformer constructs a new informer for VirtualNode 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 NewVirtualNodeInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredVirtualNodeInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredVirtualNodeInformer constructs a new informer for VirtualNode 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 NewFilteredVirtualNodeInformer(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.AppmeshV1beta2().VirtualNodes(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AppmeshV1beta2().VirtualNodes(namespace).Watch(context.TODO(), options) + }, + }, + &appmeshv1beta2.VirtualNode{}, + resyncPeriod, + indexers, + ) +} + +func (f *virtualNodeInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredVirtualNodeInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *virtualNodeInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&appmeshv1beta2.VirtualNode{}, f.defaultInformer) +} + +func (f *virtualNodeInformer) Lister() v1beta2.VirtualNodeLister { + return v1beta2.NewVirtualNodeLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/appmesh/v1beta2/virtualrouter.go b/pkg/client/informers/externalversions/appmesh/v1beta2/virtualrouter.go new file mode 100644 index 000000000..aaf4c6dee --- /dev/null +++ b/pkg/client/informers/externalversions/appmesh/v1beta2/virtualrouter.go @@ -0,0 +1,90 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + "context" + time "time" + + appmeshv1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + versioned "github.com/weaveworks/flagger/pkg/client/clientset/versioned" + internalinterfaces "github.com/weaveworks/flagger/pkg/client/informers/externalversions/internalinterfaces" + v1beta2 "github.com/weaveworks/flagger/pkg/client/listers/appmesh/v1beta2" + 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" +) + +// VirtualRouterInformer provides access to a shared informer and lister for +// VirtualRouters. +type VirtualRouterInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1beta2.VirtualRouterLister +} + +type virtualRouterInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewVirtualRouterInformer constructs a new informer for VirtualRouter 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 NewVirtualRouterInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredVirtualRouterInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredVirtualRouterInformer constructs a new informer for VirtualRouter 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 NewFilteredVirtualRouterInformer(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.AppmeshV1beta2().VirtualRouters(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AppmeshV1beta2().VirtualRouters(namespace).Watch(context.TODO(), options) + }, + }, + &appmeshv1beta2.VirtualRouter{}, + resyncPeriod, + indexers, + ) +} + +func (f *virtualRouterInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredVirtualRouterInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *virtualRouterInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&appmeshv1beta2.VirtualRouter{}, f.defaultInformer) +} + +func (f *virtualRouterInformer) Lister() v1beta2.VirtualRouterLister { + return v1beta2.NewVirtualRouterLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/appmesh/v1beta2/virtualservice.go b/pkg/client/informers/externalversions/appmesh/v1beta2/virtualservice.go new file mode 100644 index 000000000..70a33bdbb --- /dev/null +++ b/pkg/client/informers/externalversions/appmesh/v1beta2/virtualservice.go @@ -0,0 +1,90 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + "context" + time "time" + + appmeshv1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + versioned "github.com/weaveworks/flagger/pkg/client/clientset/versioned" + internalinterfaces "github.com/weaveworks/flagger/pkg/client/informers/externalversions/internalinterfaces" + v1beta2 "github.com/weaveworks/flagger/pkg/client/listers/appmesh/v1beta2" + 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" +) + +// VirtualServiceInformer provides access to a shared informer and lister for +// VirtualServices. +type VirtualServiceInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1beta2.VirtualServiceLister +} + +type virtualServiceInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewVirtualServiceInformer constructs a new informer for VirtualService 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 NewVirtualServiceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredVirtualServiceInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredVirtualServiceInformer constructs a new informer for VirtualService 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 NewFilteredVirtualServiceInformer(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.AppmeshV1beta2().VirtualServices(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AppmeshV1beta2().VirtualServices(namespace).Watch(context.TODO(), options) + }, + }, + &appmeshv1beta2.VirtualService{}, + resyncPeriod, + indexers, + ) +} + +func (f *virtualServiceInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredVirtualServiceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *virtualServiceInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&appmeshv1beta2.VirtualService{}, f.defaultInformer) +} + +func (f *virtualServiceInformer) Lister() v1beta2.VirtualServiceLister { + return v1beta2.NewVirtualServiceLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 43f86822c..ceda6adf9 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -22,6 +22,7 @@ import ( "fmt" v1beta1 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta1" + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" flaggerv1beta1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" v1 "github.com/weaveworks/flagger/pkg/apis/gloo/v1" v1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3" @@ -66,6 +67,14 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case v1beta1.SchemeGroupVersion.WithResource("virtualservices"): return &genericInformer{resource: resource.GroupResource(), informer: f.Appmesh().V1beta1().VirtualServices().Informer()}, nil + // Group=appmesh.k8s.aws, Version=v1beta2 + case v1beta2.SchemeGroupVersion.WithResource("virtualnodes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Appmesh().V1beta2().VirtualNodes().Informer()}, nil + case v1beta2.SchemeGroupVersion.WithResource("virtualrouters"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Appmesh().V1beta2().VirtualRouters().Informer()}, nil + case v1beta2.SchemeGroupVersion.WithResource("virtualservices"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Appmesh().V1beta2().VirtualServices().Informer()}, nil + // Group=flagger.app, Version=v1beta1 case flaggerv1beta1.SchemeGroupVersion.WithResource("alertproviders"): return &genericInformer{resource: resource.GroupResource(), informer: f.Flagger().V1beta1().AlertProviders().Informer()}, nil diff --git a/pkg/client/listers/appmesh/v1beta2/expansion_generated.go b/pkg/client/listers/appmesh/v1beta2/expansion_generated.go new file mode 100644 index 000000000..c57784598 --- /dev/null +++ b/pkg/client/listers/appmesh/v1beta2/expansion_generated.go @@ -0,0 +1,43 @@ +/* +Copyright The Flagger 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 v1beta2 + +// VirtualNodeListerExpansion allows custom methods to be added to +// VirtualNodeLister. +type VirtualNodeListerExpansion interface{} + +// VirtualNodeNamespaceListerExpansion allows custom methods to be added to +// VirtualNodeNamespaceLister. +type VirtualNodeNamespaceListerExpansion interface{} + +// VirtualRouterListerExpansion allows custom methods to be added to +// VirtualRouterLister. +type VirtualRouterListerExpansion interface{} + +// VirtualRouterNamespaceListerExpansion allows custom methods to be added to +// VirtualRouterNamespaceLister. +type VirtualRouterNamespaceListerExpansion interface{} + +// VirtualServiceListerExpansion allows custom methods to be added to +// VirtualServiceLister. +type VirtualServiceListerExpansion interface{} + +// VirtualServiceNamespaceListerExpansion allows custom methods to be added to +// VirtualServiceNamespaceLister. +type VirtualServiceNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/appmesh/v1beta2/virtualnode.go b/pkg/client/listers/appmesh/v1beta2/virtualnode.go new file mode 100644 index 000000000..ed62b8fd6 --- /dev/null +++ b/pkg/client/listers/appmesh/v1beta2/virtualnode.go @@ -0,0 +1,94 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// VirtualNodeLister helps list VirtualNodes. +type VirtualNodeLister interface { + // List lists all VirtualNodes in the indexer. + List(selector labels.Selector) (ret []*v1beta2.VirtualNode, err error) + // VirtualNodes returns an object that can list and get VirtualNodes. + VirtualNodes(namespace string) VirtualNodeNamespaceLister + VirtualNodeListerExpansion +} + +// virtualNodeLister implements the VirtualNodeLister interface. +type virtualNodeLister struct { + indexer cache.Indexer +} + +// NewVirtualNodeLister returns a new VirtualNodeLister. +func NewVirtualNodeLister(indexer cache.Indexer) VirtualNodeLister { + return &virtualNodeLister{indexer: indexer} +} + +// List lists all VirtualNodes in the indexer. +func (s *virtualNodeLister) List(selector labels.Selector) (ret []*v1beta2.VirtualNode, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta2.VirtualNode)) + }) + return ret, err +} + +// VirtualNodes returns an object that can list and get VirtualNodes. +func (s *virtualNodeLister) VirtualNodes(namespace string) VirtualNodeNamespaceLister { + return virtualNodeNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// VirtualNodeNamespaceLister helps list and get VirtualNodes. +type VirtualNodeNamespaceLister interface { + // List lists all VirtualNodes in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1beta2.VirtualNode, err error) + // Get retrieves the VirtualNode from the indexer for a given namespace and name. + Get(name string) (*v1beta2.VirtualNode, error) + VirtualNodeNamespaceListerExpansion +} + +// virtualNodeNamespaceLister implements the VirtualNodeNamespaceLister +// interface. +type virtualNodeNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all VirtualNodes in the indexer for a given namespace. +func (s virtualNodeNamespaceLister) List(selector labels.Selector) (ret []*v1beta2.VirtualNode, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta2.VirtualNode)) + }) + return ret, err +} + +// Get retrieves the VirtualNode from the indexer for a given namespace and name. +func (s virtualNodeNamespaceLister) Get(name string) (*v1beta2.VirtualNode, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1beta2.Resource("virtualnode"), name) + } + return obj.(*v1beta2.VirtualNode), nil +} diff --git a/pkg/client/listers/appmesh/v1beta2/virtualrouter.go b/pkg/client/listers/appmesh/v1beta2/virtualrouter.go new file mode 100644 index 000000000..5b077baa0 --- /dev/null +++ b/pkg/client/listers/appmesh/v1beta2/virtualrouter.go @@ -0,0 +1,94 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// VirtualRouterLister helps list VirtualRouters. +type VirtualRouterLister interface { + // List lists all VirtualRouters in the indexer. + List(selector labels.Selector) (ret []*v1beta2.VirtualRouter, err error) + // VirtualRouters returns an object that can list and get VirtualRouters. + VirtualRouters(namespace string) VirtualRouterNamespaceLister + VirtualRouterListerExpansion +} + +// virtualRouterLister implements the VirtualRouterLister interface. +type virtualRouterLister struct { + indexer cache.Indexer +} + +// NewVirtualRouterLister returns a new VirtualRouterLister. +func NewVirtualRouterLister(indexer cache.Indexer) VirtualRouterLister { + return &virtualRouterLister{indexer: indexer} +} + +// List lists all VirtualRouters in the indexer. +func (s *virtualRouterLister) List(selector labels.Selector) (ret []*v1beta2.VirtualRouter, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta2.VirtualRouter)) + }) + return ret, err +} + +// VirtualRouters returns an object that can list and get VirtualRouters. +func (s *virtualRouterLister) VirtualRouters(namespace string) VirtualRouterNamespaceLister { + return virtualRouterNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// VirtualRouterNamespaceLister helps list and get VirtualRouters. +type VirtualRouterNamespaceLister interface { + // List lists all VirtualRouters in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1beta2.VirtualRouter, err error) + // Get retrieves the VirtualRouter from the indexer for a given namespace and name. + Get(name string) (*v1beta2.VirtualRouter, error) + VirtualRouterNamespaceListerExpansion +} + +// virtualRouterNamespaceLister implements the VirtualRouterNamespaceLister +// interface. +type virtualRouterNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all VirtualRouters in the indexer for a given namespace. +func (s virtualRouterNamespaceLister) List(selector labels.Selector) (ret []*v1beta2.VirtualRouter, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta2.VirtualRouter)) + }) + return ret, err +} + +// Get retrieves the VirtualRouter from the indexer for a given namespace and name. +func (s virtualRouterNamespaceLister) Get(name string) (*v1beta2.VirtualRouter, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1beta2.Resource("virtualrouter"), name) + } + return obj.(*v1beta2.VirtualRouter), nil +} diff --git a/pkg/client/listers/appmesh/v1beta2/virtualservice.go b/pkg/client/listers/appmesh/v1beta2/virtualservice.go new file mode 100644 index 000000000..b87cd0e49 --- /dev/null +++ b/pkg/client/listers/appmesh/v1beta2/virtualservice.go @@ -0,0 +1,94 @@ +/* +Copyright The Flagger 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 v1beta2 + +import ( + v1beta2 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// VirtualServiceLister helps list VirtualServices. +type VirtualServiceLister interface { + // List lists all VirtualServices in the indexer. + List(selector labels.Selector) (ret []*v1beta2.VirtualService, err error) + // VirtualServices returns an object that can list and get VirtualServices. + VirtualServices(namespace string) VirtualServiceNamespaceLister + VirtualServiceListerExpansion +} + +// virtualServiceLister implements the VirtualServiceLister interface. +type virtualServiceLister struct { + indexer cache.Indexer +} + +// NewVirtualServiceLister returns a new VirtualServiceLister. +func NewVirtualServiceLister(indexer cache.Indexer) VirtualServiceLister { + return &virtualServiceLister{indexer: indexer} +} + +// List lists all VirtualServices in the indexer. +func (s *virtualServiceLister) List(selector labels.Selector) (ret []*v1beta2.VirtualService, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta2.VirtualService)) + }) + return ret, err +} + +// VirtualServices returns an object that can list and get VirtualServices. +func (s *virtualServiceLister) VirtualServices(namespace string) VirtualServiceNamespaceLister { + return virtualServiceNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// VirtualServiceNamespaceLister helps list and get VirtualServices. +type VirtualServiceNamespaceLister interface { + // List lists all VirtualServices in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1beta2.VirtualService, err error) + // Get retrieves the VirtualService from the indexer for a given namespace and name. + Get(name string) (*v1beta2.VirtualService, error) + VirtualServiceNamespaceListerExpansion +} + +// virtualServiceNamespaceLister implements the VirtualServiceNamespaceLister +// interface. +type virtualServiceNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all VirtualServices in the indexer for a given namespace. +func (s virtualServiceNamespaceLister) List(selector labels.Selector) (ret []*v1beta2.VirtualService, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta2.VirtualService)) + }) + return ret, err +} + +// Get retrieves the VirtualService from the indexer for a given namespace and name. +func (s virtualServiceNamespaceLister) Get(name string) (*v1beta2.VirtualService, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1beta2.Resource("virtualservice"), name) + } + return obj.(*v1beta2.VirtualService), nil +} diff --git a/pkg/controller/finalizer.go b/pkg/controller/finalizer.go index 505962728..4ea2a1399 100644 --- a/pkg/controller/finalizer.go +++ b/pkg/controller/finalizer.go @@ -79,7 +79,7 @@ func (c *Controller) revertMesh(r *flaggerv1.Canary) error { provider = r.Spec.Provider } - meshRouter := c.routerFactory.MeshRouter(provider) + meshRouter := c.routerFactory.MeshRouter(provider, "") if err := meshRouter.Finalize(r); err != nil { return fmt.Errorf("meshRouter.Finlize failed: %w", err) } diff --git a/pkg/controller/scheduler.go b/pkg/controller/scheduler.go index e8d9a2c39..5960df85b 100644 --- a/pkg/controller/scheduler.go +++ b/pkg/controller/scheduler.go @@ -3,6 +3,7 @@ package controller import ( "context" "fmt" + "strings" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -110,31 +111,45 @@ func (c *Controller) advanceCanary(name string, namespace string) { // init Kubernetes router kubeRouter := c.routerFactory.KubernetesRouter(cd.Spec.TargetRef.Kind, labelSelector, ports) + + // reconcile the canary/primary services if err := kubeRouter.Initialize(cd); err != nil { c.recordEventWarningf(cd, "%v", err) return } - // create primary + // init mesh router + meshRouter := c.routerFactory.MeshRouter(provider, labelSelector) + + // register the AppMesh VirtualNodes before creating the primary deployment + // otherwise the pods will not be injected with the Envoy proxy + if strings.HasPrefix(provider, flaggerv1.AppMeshProvider) { + if err := meshRouter.Reconcile(cd); err != nil { + c.recordEventWarningf(cd, "%v", err) + return + } + } + + // create primary workload err = canaryController.Initialize(cd) if err != nil { c.recordEventWarningf(cd, "%v", err) return } - // init mesh router - meshRouter := c.routerFactory.MeshRouter(provider) - - // create or update svc + // change the apex service pod selector to primary if err := kubeRouter.Reconcile(cd); err != nil { c.recordEventWarningf(cd, "%v", err) return } - // create or update mesh routes - if err := meshRouter.Reconcile(cd); err != nil { - c.recordEventWarningf(cd, "%v", err) - return + // take over an existing virtual service or ingress + // runs after the primary is ready to ensure zero downtime + if !strings.HasPrefix(provider, flaggerv1.AppMeshProvider) { + if err := meshRouter.Reconcile(cd); err != nil { + c.recordEventWarningf(cd, "%v", err) + return + } } // check for changes diff --git a/pkg/controller/scheduler_daemonset_fixture_test.go b/pkg/controller/scheduler_daemonset_fixture_test.go index cb70efcf8..02d8778cb 100644 --- a/pkg/controller/scheduler_daemonset_fixture_test.go +++ b/pkg/controller/scheduler_daemonset_fixture_test.go @@ -110,7 +110,7 @@ func newDaemonSetFixture(c *flaggerv1.Canary) daemonSetFixture { ctrl.flaggerInformers.MetricInformer.Informer().GetIndexer().Add(newDaemonSetTestMetricTemplate()) ctrl.flaggerInformers.AlertInformer.Informer().GetIndexer().Add(newDaemonSetTestAlertProvider()) - meshRouter := rf.MeshRouter("istio") + meshRouter := rf.MeshRouter("istio", "") return daemonSetFixture{ canary: c, diff --git a/pkg/controller/scheduler_deployment_fixture_test.go b/pkg/controller/scheduler_deployment_fixture_test.go index f44415d6c..fadf8366e 100644 --- a/pkg/controller/scheduler_deployment_fixture_test.go +++ b/pkg/controller/scheduler_deployment_fixture_test.go @@ -138,7 +138,7 @@ func newDeploymentFixture(c *flaggerv1.Canary) fixture { ctrl.flaggerInformers.MetricInformer.Informer().GetIndexer().Add(newDeploymentTestMetricTemplate()) ctrl.flaggerInformers.AlertInformer.Informer().GetIndexer().Add(newDeploymentTestAlertProvider()) - meshRouter := rf.MeshRouter("istio") + meshRouter := rf.MeshRouter("istio", "") return fixture{ canary: c, diff --git a/pkg/metrics/observers/crossover.go b/pkg/metrics/observers/crossover.go deleted file mode 100644 index 0ecf3d150..000000000 --- a/pkg/metrics/observers/crossover.go +++ /dev/null @@ -1,77 +0,0 @@ -package observers - -import ( - "fmt" - "time" - - flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" - "github.com/weaveworks/flagger/pkg/metrics/providers" -) - -var crossoverQueries = map[string]string{ - "request-success-rate": ` - sum( - rate( - envoy_cluster_upstream_rq{ - kubernetes_namespace="{{ namespace }}", - envoy_cluster_name=~"{{ target }}-canary", - envoy_response_code!~"5.*" - }[{{ interval }}] - ) - ) - / - sum( - rate( - envoy_cluster_upstream_rq{ - kubernetes_namespace="{{ namespace }}", - envoy_cluster_name=~"{{ target }}-canary" - }[{{ interval }}] - ) - ) - * 100`, - "request-duration": ` - histogram_quantile( - 0.99, - sum( - rate( - envoy_cluster_upstream_rq_time_bucket{ - kubernetes_namespace="{{ namespace }}", - envoy_cluster_name=~"{{ target }}-canary" - }[{{ interval }}] - ) - ) by (le) - )`, -} - -type CrossoverObserver struct { - client providers.Interface -} - -func (ob *CrossoverObserver) GetRequestSuccessRate(model flaggerv1.MetricTemplateModel) (float64, error) { - query, err := RenderQuery(crossoverQueries["request-success-rate"], model) - if err != nil { - return 0, err - } - - value, err := ob.client.RunQuery(query) - if err != nil { - return 0, err - } - - return value, nil -} - -func (ob *CrossoverObserver) GetRequestDuration(model flaggerv1.MetricTemplateModel) (time.Duration, error) { - query, err := RenderQuery(crossoverQueries["request-duration"], model) - if err != nil { - return 0, fmt.Errorf("rendering query failed: %w", err) - } - - value, err := ob.client.RunQuery(query) - if err != nil { - return 0, fmt.Errorf("running query failed: %w", err) - } - - ms := time.Duration(int64(value)) * time.Millisecond - return ms, nil -} diff --git a/pkg/metrics/observers/crossover_service.go b/pkg/metrics/observers/crossover_service.go deleted file mode 100644 index 0aa27a6a3..000000000 --- a/pkg/metrics/observers/crossover_service.go +++ /dev/null @@ -1,77 +0,0 @@ -package observers - -import ( - "fmt" - "time" - - flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" - "github.com/weaveworks/flagger/pkg/metrics/providers" -) - -var crossoverServiceQueries = map[string]string{ - "request-success-rate": ` - sum( - rate( - envoy_cluster_upstream_rq{ - kubernetes_namespace="{{ namespace }}", - envoy_cluster_name="{{ target }}-canary", - envoy_response_code!~"5.*" - }[{{ interval }}] - ) - ) - / - sum( - rate( - envoy_cluster_upstream_rq{ - kubernetes_namespace="{{ namespace }}", - envoy_cluster_name="{{ target }}-canary" - }[{{ interval }}] - ) - ) - * 100`, - "request-duration": ` - histogram_quantile( - 0.99, - sum( - rate( - envoy_cluster_upstream_rq_time_bucket{ - kubernetes_namespace="{{ namespace }}", - envoy_cluster_name="{{ target }}-canary" - }[{{ interval }}] - ) - ) by (le) - )`, -} - -type CrossoverServiceObserver struct { - client providers.Interface -} - -func (ob *CrossoverServiceObserver) GetRequestSuccessRate(model flaggerv1.MetricTemplateModel) (float64, error) { - query, err := RenderQuery(crossoverServiceQueries["request-success-rate"], model) - if err != nil { - return 0, fmt.Errorf("rendering query failed: %w", err) - } - - value, err := ob.client.RunQuery(query) - if err != nil { - return 0, fmt.Errorf("running query failed: %w", err) - } - - return value, nil -} - -func (ob *CrossoverServiceObserver) GetRequestDuration(model flaggerv1.MetricTemplateModel) (time.Duration, error) { - query, err := RenderQuery(crossoverServiceQueries["request-duration"], model) - if err != nil { - return 0, fmt.Errorf("rendering query failed: %w", err) - } - - value, err := ob.client.RunQuery(query) - if err != nil { - return 0, fmt.Errorf("running query failed: %w", err) - } - - ms := time.Duration(int64(value)) * time.Millisecond - return ms, nil -} diff --git a/pkg/metrics/observers/crossover_service_test.go b/pkg/metrics/observers/crossover_service_test.go deleted file mode 100644 index b0c9fc4e3..000000000 --- a/pkg/metrics/observers/crossover_service_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package observers - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" - "github.com/weaveworks/flagger/pkg/metrics/providers" -) - -func TestCrossoverServiceObserver_GetRequestSuccessRate(t *testing.T) { - expected := ` sum( rate( envoy_cluster_upstream_rq{ kubernetes_namespace="default", envoy_cluster_name="podinfo-canary", envoy_response_code!~"5.*" }[1m] ) ) / sum( rate( envoy_cluster_upstream_rq{ kubernetes_namespace="default", envoy_cluster_name="podinfo-canary" }[1m] ) ) * 100` - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - promql := r.URL.Query()["query"][0] - assert.Equal(t, expected, promql) - - json := `{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1,"100"]}]}}` - w.Write([]byte(json)) - })) - defer ts.Close() - - client, err := providers.NewPrometheusProvider(flaggerv1.MetricTemplateProvider{ - Type: "prometheus", - Address: ts.URL, - SecretRef: nil, - }, nil) - require.NoError(t, err) - - observer := &CrossoverServiceObserver{ - client: client, - } - - val, err := observer.GetRequestSuccessRate(flaggerv1.MetricTemplateModel{ - Name: "podinfo", - Namespace: "default", - Target: "podinfo", - Service: "podinfo", - Interval: "1m", - }) - require.NoError(t, err) - - assert.Equal(t, float64(100), val) -} - -func TestCrossoverServiceObserver_GetRequestDuration(t *testing.T) { - expected := ` histogram_quantile( 0.99, sum( rate( envoy_cluster_upstream_rq_time_bucket{ kubernetes_namespace="default", envoy_cluster_name="podinfo-canary" }[1m] ) ) by (le) )` - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - promql := r.URL.Query()["query"][0] - assert.Equal(t, expected, promql) - - json := `{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1,"100"]}]}}` - w.Write([]byte(json)) - })) - defer ts.Close() - - client, err := providers.NewPrometheusProvider(flaggerv1.MetricTemplateProvider{ - Type: "prometheus", - Address: ts.URL, - SecretRef: nil, - }, nil) - require.NoError(t, err) - - observer := &CrossoverServiceObserver{ - client: client, - } - - val, err := observer.GetRequestDuration(flaggerv1.MetricTemplateModel{ - Name: "podinfo", - Namespace: "default", - Target: "podinfo", - Service: "podinfo", - Interval: "1m", - }) - require.NoError(t, err) - - assert.Equal(t, 100*time.Millisecond, val) -} diff --git a/pkg/metrics/observers/crossover_test.go b/pkg/metrics/observers/crossover_test.go deleted file mode 100644 index 7cf6ed65d..000000000 --- a/pkg/metrics/observers/crossover_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package observers - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" - "github.com/weaveworks/flagger/pkg/metrics/providers" -) - -func TestCrossoverObserver_GetRequestSuccessRate(t *testing.T) { - expected := ` sum( rate( envoy_cluster_upstream_rq{ kubernetes_namespace="default", envoy_cluster_name=~"podinfo-canary", envoy_response_code!~"5.*" }[1m] ) ) / sum( rate( envoy_cluster_upstream_rq{ kubernetes_namespace="default", envoy_cluster_name=~"podinfo-canary" }[1m] ) ) * 100` - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - promql := r.URL.Query()["query"][0] - assert.Equal(t, expected, promql) - - json := `{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1,"100"]}]}}` - w.Write([]byte(json)) - })) - defer ts.Close() - - client, err := providers.NewPrometheusProvider(flaggerv1.MetricTemplateProvider{ - Type: "prometheus", - Address: ts.URL, - SecretRef: nil, - }, nil) - require.NoError(t, err) - - observer := &CrossoverObserver{ - client: client, - } - - val, err := observer.GetRequestSuccessRate(flaggerv1.MetricTemplateModel{ - Name: "podinfo", - Namespace: "default", - Target: "podinfo", - Service: "podinfo", - Interval: "1m", - }) - require.NoError(t, err) - - assert.Equal(t, float64(100), val) -} - -func TestCrossoverObserver_GetRequestDuration(t *testing.T) { - expected := ` histogram_quantile( 0.99, sum( rate( envoy_cluster_upstream_rq_time_bucket{ kubernetes_namespace="default", envoy_cluster_name=~"podinfo-canary" }[1m] ) ) by (le) )` - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - promql := r.URL.Query()["query"][0] - assert.Equal(t, expected, promql) - - json := `{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1,"100"]}]}}` - w.Write([]byte(json)) - })) - defer ts.Close() - - client, err := providers.NewPrometheusProvider(flaggerv1.MetricTemplateProvider{ - Type: "prometheus", - Address: ts.URL, - SecretRef: nil, - }, nil) - require.NoError(t, err) - - observer := &CrossoverObserver{ - client: client, - } - - val, err := observer.GetRequestDuration(flaggerv1.MetricTemplateModel{ - Name: "podinfo", - Namespace: "default", - Target: "podinfo", - Service: "podinfo", - Interval: "1m", - }) - require.NoError(t, err) - - assert.Equal(t, 100*time.Millisecond, val) -} diff --git a/pkg/metrics/observers/factory.go b/pkg/metrics/observers/factory.go index f335354f7..35555c7c7 100644 --- a/pkg/metrics/observers/factory.go +++ b/pkg/metrics/observers/factory.go @@ -28,44 +28,32 @@ func NewFactory(metricsServer string) (*Factory, error) { func (factory Factory) Observer(provider string) Interface { switch { - case provider == "none": - return &HttpObserver{ - client: factory.Client, - } - case provider == "kubernetes": - return &HttpObserver{ - client: factory.Client, - } - case provider == "appmesh": + case strings.HasPrefix(provider, flaggerv1.AppMeshProvider): return &AppMeshObserver{ client: factory.Client, } - case provider == "crossover": - return &CrossoverObserver{ - client: factory.Client, - } - case provider == "nginx": - return &NginxObserver{ + case provider == flaggerv1.LinkerdProvider: + return &LinkerdObserver{ client: factory.Client, } - case strings.HasPrefix(provider, "gloo"): - return &GlooObserver{ + case provider == flaggerv1.IstioProvider: + return &IstioObserver{ client: factory.Client, } - case provider == "smi:linkerd": - return &LinkerdObserver{ + case provider == flaggerv1.ContourProvider: + return &ContourObserver{ client: factory.Client, } - case provider == "crossover:service": - return &CrossoverServiceObserver{ + case strings.HasPrefix(provider, flaggerv1.GlooProvider): + return &GlooObserver{ client: factory.Client, } - case provider == "linkerd": - return &LinkerdObserver{ + case provider == flaggerv1.NGINXProvider: + return &NginxObserver{ client: factory.Client, } - case provider == "contour": - return &ContourObserver{ + case provider == flaggerv1.KubernetesProvider: + return &HttpObserver{ client: factory.Client, } default: diff --git a/pkg/router/appmesh_v1beta2.go b/pkg/router/appmesh_v1beta2.go new file mode 100644 index 000000000..527099fc0 --- /dev/null +++ b/pkg/router/appmesh_v1beta2.go @@ -0,0 +1,540 @@ +package router + +import ( + "context" + "fmt" + "strconv" + "strings" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "go.uber.org/zap" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes" + + appmeshv1 "github.com/weaveworks/flagger/pkg/apis/appmesh/v1beta2" + flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" + clientset "github.com/weaveworks/flagger/pkg/client/clientset/versioned" +) + +// AppMeshRouter is managing AppMesh virtual services +type AppMeshv1beta2Router struct { + kubeClient kubernetes.Interface + appmeshClient clientset.Interface + flaggerClient clientset.Interface + logger *zap.SugaredLogger + labelSelector string +} + +// Reconcile creates or updates App Mesh virtual nodes and virtual services +func (ar *AppMeshv1beta2Router) Reconcile(canary *flaggerv1.Canary) error { + svcSuffix := "svc.cluster.local." + apexName, primaryName, canaryName := canary.GetServiceNames() + primaryHost := fmt.Sprintf("%s.%s.%s", primaryName, canary.Namespace, svcSuffix) + canaryHost := fmt.Sprintf("%s.%s.%s", canaryName, canary.Namespace, svcSuffix) + + // sync virtual node e.g. app-namespace + // DNS app.namespace + //err := ar.reconcileVirtualNode(canary, apexName, fmt.Sprintf("%s-primary", canary.Spec.TargetRef.Name), primaryHost) + //if err != nil { + // return fmt.Errorf("reconcileVirtualNode failed: %w", err) + //} + + // sync virtual node e.g. app-primary-namespace + // DNS app-primary.namespace + err := ar.reconcileVirtualNode(canary, primaryName, fmt.Sprintf("%s-primary", canary.Spec.TargetRef.Name), primaryHost) + if err != nil { + return fmt.Errorf("reconcileVirtualNode failed: %w", err) + } + + // sync virtual node e.g. app-canary-namespace + // DNS app-canary.namespace + err = ar.reconcileVirtualNode(canary, canaryName, canary.Spec.TargetRef.Name, canaryHost) + if err != nil { + return fmt.Errorf("reconcileVirtualNode failed: %w", err) + } + + // sync main virtual router + // DNS app.namespace + err = ar.reconcileVirtualRouter(canary, apexName, 0) + if err != nil { + return fmt.Errorf("reconcileVirtualService failed: %w", err) + } + + // sync canary virtual router + // DNS app-canary.namespace + err = ar.reconcileVirtualRouter(canary, canaryName, 100) + if err != nil { + return fmt.Errorf("reconcileVirtualRouter failed: %w", err) + } + + return nil +} + +// reconcileVirtualNode creates or updates a virtual node +// the virtual node naming format is name-role-namespace +func (ar *AppMeshv1beta2Router) reconcileVirtualNode(canary *flaggerv1.Canary, name string, podSelector string, host string) error { + protocol := ar.getProtocol(canary) + vnSpec := appmeshv1.VirtualNodeSpec{ + Listeners: []appmeshv1.Listener{ + { + PortMapping: appmeshv1.PortMapping{ + Port: ar.getContainerPort(canary), + Protocol: protocol, + }, + }, + }, + ServiceDiscovery: &appmeshv1.ServiceDiscovery{ + DNS: &appmeshv1.DNSServiceDiscovery{ + Hostname: host, + }, + }, + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + ar.labelSelector: podSelector, + }, + }, + } + + backends := make([]appmeshv1.Backend, 0) + for _, b := range canary.Spec.Service.Backends { + bk := appmeshv1.Backend{ + VirtualService: appmeshv1.VirtualServiceBackend{ + VirtualServiceRef: appmeshv1.VirtualServiceReference{ + Name: b, + }, + }, + } + backends = append(backends, bk) + } + + if len(backends) > 0 { + vnSpec.Backends = backends + } + + virtualnode, err := ar.appmeshClient.AppmeshV1beta2().VirtualNodes(canary.Namespace).Get(context.TODO(), name, metav1.GetOptions{}) + + // create virtual node + if errors.IsNotFound(err) { + virtualnode = &appmeshv1.VirtualNode{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: canary.Namespace, + OwnerReferences: []metav1.OwnerReference{ + *metav1.NewControllerRef(canary, schema.GroupVersionKind{ + Group: flaggerv1.SchemeGroupVersion.Group, + Version: flaggerv1.SchemeGroupVersion.Version, + Kind: flaggerv1.CanaryKind, + }), + }, + }, + Spec: vnSpec, + } + _, err = ar.appmeshClient.AppmeshV1beta2().VirtualNodes(canary.Namespace).Create(context.TODO(), virtualnode, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("VirtualNode %s.%s create error %w", name, canary.Namespace, err) + } + ar.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)). + Infof("VirtualNode %s.%s created", virtualnode.GetName(), canary.Namespace) + return nil + } else if err != nil { + return fmt.Errorf("VirtualNode %s get query error %w", name, err) + } + + // update virtual node + if virtualnode != nil { + if diff := cmp.Diff(vnSpec, virtualnode.Spec, + cmpopts.IgnoreFields(appmeshv1.VirtualNodeSpec{}, "AWSName", "MeshRef")); diff != "" { + vnClone := virtualnode.DeepCopy() + vnClone.Spec = vnSpec + vnClone.Spec.AWSName = virtualnode.Spec.AWSName + vnClone.Spec.MeshRef = virtualnode.Spec.MeshRef + _, err = ar.appmeshClient.AppmeshV1beta2().VirtualNodes(canary.Namespace).Update(context.TODO(), vnClone, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("VirtualNode %s update error %w", name, err) + } + ar.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)). + Infof("VirtualNode %s updated", virtualnode.GetName()) + } + } + + return nil +} + +// reconcileVirtualRouter creates or updates a virtual router +func (ar *AppMeshv1beta2Router) reconcileVirtualRouter(canary *flaggerv1.Canary, name string, canaryWeight int64) error { + apexName, _, _ := canary.GetServiceNames() + canaryVirtualNode := fmt.Sprintf("%s-canary", apexName) + primaryVirtualNode := fmt.Sprintf("%s-primary", apexName) + protocol := ar.getProtocol(canary) + + routerName := apexName + if canaryWeight > 0 { + routerName = fmt.Sprintf("%s-canary", apexName) + } + // App Mesh supports only URI prefix + routePrefix := "/" + if len(canary.Spec.Service.Match) > 0 && + canary.Spec.Service.Match[0].Uri != nil && + canary.Spec.Service.Match[0].Uri.Prefix != "" { + routePrefix = canary.Spec.Service.Match[0].Uri.Prefix + } + + // Canary progressive traffic shift + routes := []appmeshv1.Route{ + { + Name: routerName, + HTTPRoute: &appmeshv1.HTTPRoute{ + Match: appmeshv1.HTTPRouteMatch{ + Prefix: routePrefix, + }, + RetryPolicy: ar.makeRetryPolicy(canary), + Action: appmeshv1.HTTPRouteAction{ + WeightedTargets: []appmeshv1.WeightedTarget{ + { + VirtualNodeRef: appmeshv1.VirtualNodeReference{ + Name: canaryVirtualNode, + }, + Weight: canaryWeight, + }, + { + VirtualNodeRef: appmeshv1.VirtualNodeReference{ + Name: primaryVirtualNode, + }, + Weight: 100 - canaryWeight, + }, + }, + }, + }, + }, + } + + // A/B testing - header based routing + if len(canary.GetAnalysis().Match) > 0 && canaryWeight == 0 { + routes = []appmeshv1.Route{ + { + Name: fmt.Sprintf("%s-a", apexName), + Priority: int64p(10), + HTTPRoute: &appmeshv1.HTTPRoute{ + Match: appmeshv1.HTTPRouteMatch{ + Prefix: routePrefix, + Headers: ar.makeHeaders(canary), + }, + RetryPolicy: ar.makeRetryPolicy(canary), + Action: appmeshv1.HTTPRouteAction{ + WeightedTargets: []appmeshv1.WeightedTarget{ + { + VirtualNodeRef: appmeshv1.VirtualNodeReference{ + Name: canaryVirtualNode, + }, + Weight: canaryWeight, + }, + { + VirtualNodeRef: appmeshv1.VirtualNodeReference{ + Name: primaryVirtualNode, + }, + Weight: 100 - canaryWeight, + }, + }, + }, + }, + }, + { + Name: fmt.Sprintf("%s-b", apexName), + Priority: int64p(20), + HTTPRoute: &appmeshv1.HTTPRoute{ + Match: appmeshv1.HTTPRouteMatch{ + Prefix: routePrefix, + }, + RetryPolicy: ar.makeRetryPolicy(canary), + Action: appmeshv1.HTTPRouteAction{ + WeightedTargets: []appmeshv1.WeightedTarget{ + { + VirtualNodeRef: appmeshv1.VirtualNodeReference{ + Name: primaryVirtualNode, + }, + Weight: 100, + }, + }, + }, + }, + }, + } + } + + vrSpec := appmeshv1.VirtualRouterSpec{ + Listeners: []appmeshv1.VirtualRouterListener{ + { + PortMapping: appmeshv1.PortMapping{ + Port: ar.getContainerPort(canary), + Protocol: protocol, + }, + }, + }, + Routes: routes, + } + + virtualRouter, err := ar.appmeshClient.AppmeshV1beta2().VirtualRouters(canary.Namespace).Get(context.TODO(), name, metav1.GetOptions{}) + + // create virtual router + if errors.IsNotFound(err) { + virtualRouter = &appmeshv1.VirtualRouter{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: canary.Namespace, + OwnerReferences: []metav1.OwnerReference{ + *metav1.NewControllerRef(canary, schema.GroupVersionKind{ + Group: flaggerv1.SchemeGroupVersion.Group, + Version: flaggerv1.SchemeGroupVersion.Version, + Kind: flaggerv1.CanaryKind, + }), + }, + }, + Spec: vrSpec, + } + + _, err = ar.appmeshClient.AppmeshV1beta2().VirtualRouters(canary.Namespace).Create(context.TODO(), virtualRouter, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("VirtualRouter %s create error %w", name, err) + } + ar.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)). + Infof("VirtualRouter %s created", virtualRouter.GetName()) + + virtualService := &appmeshv1.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: canary.Namespace, + OwnerReferences: []metav1.OwnerReference{ + *metav1.NewControllerRef(canary, schema.GroupVersionKind{ + Group: flaggerv1.SchemeGroupVersion.Group, + Version: flaggerv1.SchemeGroupVersion.Version, + Kind: flaggerv1.CanaryKind, + }), + }, + }, + Spec: appmeshv1.VirtualServiceSpec{ + Provider: &appmeshv1.VirtualServiceProvider{ + VirtualRouter: &appmeshv1.VirtualRouterServiceProvider{ + VirtualRouterRef: appmeshv1.VirtualRouterReference{ + Name: name, + }, + }, + }, + }, + } + + // set App Mesh Gateway annotation on primary virtual service + if canaryWeight == 0 { + a := ar.gatewayAnnotations(canary) + if len(a) > 0 { + virtualService.ObjectMeta.Annotations = a + } + } + + _, err = ar.appmeshClient.AppmeshV1beta2().VirtualServices(canary.Namespace).Create(context.TODO(), virtualService, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("VirtualService %s create error %w", name, err) + } + ar.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)). + Infof("VirtualService %s created", virtualRouter.GetName()) + + return nil + } else if err != nil { + return fmt.Errorf("VirtualRouter %s get query error: %w", name, err) + } + + // update virtual router but keep the original target weights + if virtualRouter != nil { + if diff := cmp.Diff(vrSpec, virtualRouter.Spec, + cmpopts.IgnoreFields(appmeshv1.VirtualRouterSpec{}, "AWSName", "MeshRef"), + cmpopts.IgnoreTypes(appmeshv1.WeightedTarget{}, appmeshv1.MeshReference{})); diff != "" { + vrClone := virtualRouter.DeepCopy() + vrClone.Spec = vrSpec + vrClone.Spec.Routes[0].HTTPRoute.Action = virtualRouter.Spec.Routes[0].HTTPRoute.Action + vrClone.Spec.AWSName = virtualRouter.Spec.AWSName + vrClone.Spec.MeshRef = virtualRouter.Spec.MeshRef + _, err = ar.appmeshClient.AppmeshV1beta2().VirtualRouters(canary.Namespace).Update(context.TODO(), vrClone, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("VirtualRouter %s update error: %w", name, err) + } + ar.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)). + Infof("VirtualRouter %s updated", virtualRouter.GetName()) + } + } + + return nil +} + +// GetRoutes returns the destinations weight for primary and canary +func (ar *AppMeshv1beta2Router) GetRoutes(canary *flaggerv1.Canary) ( + primaryWeight int, + canaryWeight int, + mirrored bool, + err error, +) { + apexName, primaryName, canaryName := canary.GetServiceNames() + virtualRouter, err := ar.appmeshClient.AppmeshV1beta2().VirtualRouters(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{}) + if err != nil { + err = fmt.Errorf("VirtualRouter %s get query error: %w", apexName, err) + return + } + + if len(virtualRouter.Spec.Routes) < 1 || len(virtualRouter.Spec.Routes[0].HTTPRoute.Action.WeightedTargets) != 2 { + err = fmt.Errorf("VirtualRouter routes %s not found", apexName) + return + } + + targets := virtualRouter.Spec.Routes[0].HTTPRoute.Action.WeightedTargets + for _, t := range targets { + if t.VirtualNodeRef.Name == canaryName { + canaryWeight = int(t.Weight) + } + if t.VirtualNodeRef.Name == primaryName { + primaryWeight = int(t.Weight) + } + } + + if primaryWeight == 0 && canaryWeight == 0 { + err = fmt.Errorf("VirtualRouter %s does not contain routes for %s-primary and %s-canary", + apexName, apexName, apexName) + } + + mirrored = false + + return +} + +// SetRoutes updates the destinations weight for primary and canary +func (ar *AppMeshv1beta2Router) SetRoutes( + canary *flaggerv1.Canary, + primaryWeight int, + canaryWeight int, + _ bool, +) error { + apexName, primaryName, canaryName := canary.GetServiceNames() + virtualRouter, err := ar.appmeshClient.AppmeshV1beta2().VirtualRouters(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("VirtualRouter %s get query error: %w", apexName, err) + } + + vrClone := virtualRouter.DeepCopy() + vrClone.Spec.Routes[0].HTTPRoute.Action = appmeshv1.HTTPRouteAction{ + WeightedTargets: []appmeshv1.WeightedTarget{ + { + VirtualNodeRef: appmeshv1.VirtualNodeReference{ + Name: canaryName, + }, + Weight: int64(canaryWeight), + }, + { + VirtualNodeRef: appmeshv1.VirtualNodeReference{ + Name: primaryName, + }, + Weight: int64(primaryWeight), + }, + }, + } + + _, err = ar.appmeshClient.AppmeshV1beta2().VirtualRouters(canary.Namespace).Update(context.TODO(), vrClone, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("VirtualRouter %s update error: %w", apexName, err) + } + return nil +} + +// makeRetryPolicy creates an AppMesh HTTPRetryPolicy from the Canary.Service.Retries +// default: one retry on gateway error with a 250ms timeout +func (ar *AppMeshv1beta2Router) makeRetryPolicy(canary *flaggerv1.Canary) *appmeshv1.HTTPRetryPolicy { + if canary.Spec.Service.Retries != nil { + timeout := int64(250) + if d, err := time.ParseDuration(canary.Spec.Service.Retries.PerTryTimeout); err == nil { + timeout = d.Milliseconds() + } + + attempts := 1 + if canary.Spec.Service.Retries.Attempts > 0 { + attempts = canary.Spec.Service.Retries.Attempts + } + retryPolicy := &appmeshv1.HTTPRetryPolicy{ + PerRetryTimeout: appmeshv1.Duration{ + Unit: appmeshv1.DurationUnitMS, + Value: timeout, + }, + MaxRetries: int64(attempts), + } + + events := []string{"gateway-error"} + if len(canary.Spec.Service.Retries.RetryOn) > 0 { + events = strings.Split(canary.Spec.Service.Retries.RetryOn, ",") + } + for _, value := range events { + retryPolicy.HTTPRetryEvents = append(retryPolicy.HTTPRetryEvents, appmeshv1.HTTPRetryPolicyEvent(value)) + } + return retryPolicy + } + + return nil +} + +// makeRetryPolicy creates an App Mesh HttpRouteHeader from the Canary.CanaryAnalysis.Match +func (ar *AppMeshv1beta2Router) makeHeaders(canary *flaggerv1.Canary) []appmeshv1.HTTPRouteHeader { + + var headers []appmeshv1.HTTPRouteHeader + for _, m := range canary.GetAnalysis().Match { + for key, value := range m.Headers { + header := appmeshv1.HTTPRouteHeader{ + Name: key, + Match: &appmeshv1.HeaderMatchMethod{ + Exact: stringp(value.Exact), + Prefix: stringp(value.Prefix), + Regex: stringp(value.Regex), + Suffix: stringp(value.Suffix), + }, + } + headers = append(headers, header) + } + } + + return headers +} + +func (ar *AppMeshv1beta2Router) getProtocol(canary *flaggerv1.Canary) appmeshv1.PortProtocol { + if strings.Contains(canary.Spec.Service.PortName, "grpc") { + return appmeshv1.PortProtocolGRPC + } + return appmeshv1.PortProtocolHTTP +} + +func (ar *AppMeshv1beta2Router) getContainerPort(canary *flaggerv1.Canary) appmeshv1.PortNumber { + containerPort := canary.Spec.Service.Port + if canary.Spec.Service.TargetPort.IntVal > 0 { + containerPort = canary.Spec.Service.TargetPort.IntVal + } + return appmeshv1.PortNumber(containerPort) +} + +func (ar *AppMeshv1beta2Router) gatewayAnnotations(canary *flaggerv1.Canary) map[string]string { + a := make(map[string]string) + domains := "" + for _, value := range canary.Spec.Service.Hosts { + domains += value + "," + } + if domains != "" { + a["gateway.appmesh.k8s.aws/expose"] = "true" + a["gateway.appmesh.k8s.aws/domain"] = domains + if canary.Spec.Service.Timeout != "" { + a["gateway.appmesh.k8s.aws/timeout"] = canary.Spec.Service.Timeout + } + if canary.Spec.Service.Retries != nil && canary.Spec.Service.Retries.Attempts > 0 { + a["gateway.appmesh.k8s.aws/retries"] = strconv.Itoa(canary.Spec.Service.Retries.Attempts) + } + } + return a +} + +func (ar *AppMeshv1beta2Router) Finalize(_ *flaggerv1.Canary) error { + return nil +} diff --git a/pkg/router/appmesh_v1beta2_test.go b/pkg/router/appmesh_v1beta2_test.go new file mode 100644 index 000000000..9425cc3fa --- /dev/null +++ b/pkg/router/appmesh_v1beta2_test.go @@ -0,0 +1,162 @@ +package router + +import ( + "context" + "fmt" + "strconv" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestAppmeshv1beta2Router_Reconcile(t *testing.T) { + mocks := newFixture(nil) + router := &AppMeshv1beta2Router{ + logger: mocks.logger, + flaggerClient: mocks.flaggerClient, + appmeshClient: mocks.meshClient, + kubeClient: mocks.kubeClient, + } + + apexName, primaryName, canaryName := mocks.appmeshCanary.GetServiceNames() + err := router.Reconcile(mocks.appmeshCanary) + require.NoError(t, err) + + // check apex virtual service + _, err = router.appmeshClient.AppmeshV1beta2().VirtualServices("default").Get(context.TODO(), apexName, metav1.GetOptions{}) + require.NoError(t, err) + + // check canary virtual service + _, err = router.appmeshClient.AppmeshV1beta2().VirtualServices("default").Get(context.TODO(), canaryName, metav1.GetOptions{}) + require.NoError(t, err) + + // check apex virtual router + vrApex, err := router.appmeshClient.AppmeshV1beta2().VirtualRouters("default").Get(context.TODO(), apexName, metav1.GetOptions{}) + require.NoError(t, err) + assert.Len(t, vrApex.Spec.Routes[0].HTTPRoute.Action.WeightedTargets, 2) + + // check canary virtual router + vrCanary, err := router.appmeshClient.AppmeshV1beta2().VirtualRouters("default").Get(context.TODO(), canaryName, metav1.GetOptions{}) + require.NoError(t, err) + + // check if the canary virtual service routes all traffic to the canary virtual node + target := vrCanary.Spec.Routes[0].HTTPRoute.Action.WeightedTargets[0] + assert.Equal(t, canaryName, target.VirtualNodeRef.Name) + assert.Equal(t, int64(100), target.Weight) + + // check primary virtual node + vnPrimary, err := router.appmeshClient.AppmeshV1beta2().VirtualNodes("default").Get(context.TODO(), primaryName, metav1.GetOptions{}) + require.NoError(t, err) + + primaryDNS := fmt.Sprintf("%s.%s.svc.cluster.local.", primaryName, mocks.appmeshCanary.Namespace) + assert.Equal(t, primaryDNS, vnPrimary.Spec.ServiceDiscovery.DNS.Hostname) + + // test backends update + cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get(context.TODO(), mocks.appmeshCanary.Name, metav1.GetOptions{}) + require.NoError(t, err) + + cdClone := cd.DeepCopy() + backends := cdClone.Spec.Service.Backends + backends = append(backends, "test.example.com") + cdClone.Spec.Service.Backends = backends + canary, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Update(context.TODO(), cdClone, metav1.UpdateOptions{}) + require.NoError(t, err) + + // apply change + err = router.Reconcile(canary) + require.NoError(t, err) + + // verify + vnPrimary, err = router.appmeshClient.AppmeshV1beta2().VirtualNodes("default").Get(context.TODO(), primaryName, metav1.GetOptions{}) + require.NoError(t, err) + require.Len(t, vnPrimary.Spec.Backends, 2) + + // update URI + vrClone := vrApex.DeepCopy() + vrClone.Spec.Routes[0].HTTPRoute.Match.Prefix = "api" + vrApex, err = mocks.meshClient.AppmeshV1beta2().VirtualRouters("default").Update(context.TODO(), vrClone, metav1.UpdateOptions{}) + require.NoError(t, err) + + // undo URI change + err = router.Reconcile(canary) + require.NoError(t, err) + vrApex, err = router.appmeshClient.AppmeshV1beta2().VirtualRouters("default").Get(context.TODO(), apexName, metav1.GetOptions{}) + require.NoError(t, err) + assert.Equal(t, "/", vrApex.Spec.Routes[0].HTTPRoute.Match.Prefix) +} + +func TestAppmeshv1beta2Router_GetSetRoutes(t *testing.T) { + mocks := newFixture(nil) + router := &AppMeshv1beta2Router{ + logger: mocks.logger, + flaggerClient: mocks.flaggerClient, + appmeshClient: mocks.meshClient, + kubeClient: mocks.kubeClient, + } + + err := router.Reconcile(mocks.appmeshCanary) + require.NoError(t, err) + + err = router.SetRoutes(mocks.appmeshCanary, 60, 40, false) + require.NoError(t, err) + + p, c, m, err := router.GetRoutes(mocks.appmeshCanary) + require.NoError(t, err) + assert.Equal(t, 60, p) + assert.Equal(t, 40, c) + assert.False(t, m) +} + +func TestAppmesv1beta2hRouter_ABTest(t *testing.T) { + mocks := newFixture(nil) + router := &AppMeshv1beta2Router{ + logger: mocks.logger, + flaggerClient: mocks.flaggerClient, + appmeshClient: mocks.meshClient, + kubeClient: mocks.kubeClient, + } + + apexName, _, _ := mocks.abtest.GetServiceNames() + err := router.Reconcile(mocks.abtest) + require.NoError(t, err) + + vrApex, err := router.appmeshClient.AppmeshV1beta2().VirtualRouters("default").Get(context.TODO(), apexName, metav1.GetOptions{}) + require.NoError(t, err) + + // check routes + assert.Len(t, vrApex.Spec.Routes, 2) + + // check headers + assert.GreaterOrEqual(t, len(vrApex.Spec.Routes[0].HTTPRoute.Match.Headers), 1, "Got no http match headers") + assert.Equal(t, "x-user-type", vrApex.Spec.Routes[0].HTTPRoute.Match.Headers[0].Name) + assert.Equal(t, "test", *vrApex.Spec.Routes[0].HTTPRoute.Match.Headers[0].Match.Exact) +} + +func TestAppmeshv1beta2Router_Gateway(t *testing.T) { + mocks := newFixture(nil) + router := &AppMeshv1beta2Router{ + logger: mocks.logger, + flaggerClient: mocks.flaggerClient, + appmeshClient: mocks.meshClient, + kubeClient: mocks.kubeClient, + } + + apexName, _, _ := mocks.appmeshCanary.GetServiceNames() + err := router.Reconcile(mocks.appmeshCanary) + require.NoError(t, err) + + vs, err := router.appmeshClient.AppmeshV1beta2().VirtualServices("default").Get(context.TODO(), apexName, metav1.GetOptions{}) + require.NoError(t, err) + + // check Flagger's gateway annotations + assert.Equal(t, "true", vs.Annotations["gateway.appmesh.k8s.aws/expose"]) + assert.True(t, strings.Contains(vs.Annotations["gateway.appmesh.k8s.aws/domain"], mocks.appmeshCanary.Spec.Service.Hosts[0])) + assert.Equal(t, mocks.appmeshCanary.Spec.Service.Timeout, vs.Annotations["gateway.appmesh.k8s.aws/timeout"]) + + retries := vs.Annotations["gateway.appmesh.k8s.aws/retries"] + assert.Equal(t, strconv.Itoa(mocks.appmeshCanary.Spec.Service.Retries.Attempts), retries) +} diff --git a/pkg/router/factory.go b/pkg/router/factory.go index 5e28868a4..9efcf8a6b 100644 --- a/pkg/router/factory.go +++ b/pkg/router/factory.go @@ -7,6 +7,7 @@ import ( "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" + flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" clientset "github.com/weaveworks/flagger/pkg/client/clientset/versioned" ) @@ -51,53 +52,58 @@ func (factory *Factory) KubernetesRouter(kind string, labelSelector string, port } // MeshRouter returns a service mesh router -func (factory *Factory) MeshRouter(provider string) Interface { +func (factory *Factory) MeshRouter(provider string, labelSelector string) Interface { switch { - case provider == "none": - return &NopRouter{} - case provider == "kubernetes": - return &NopRouter{} - case provider == "nginx": - return &IngressRouter{ - logger: factory.logger, - kubeClient: factory.kubeClient, - annotationsPrefix: factory.ingressAnnotationsPrefix, + case strings.HasPrefix(provider, flaggerv1.AppMeshProvider+":v1beta2"): + return &AppMeshv1beta2Router{ + logger: factory.logger, + flaggerClient: factory.flaggerClient, + kubeClient: factory.kubeClient, + appmeshClient: factory.meshClient, + labelSelector: labelSelector, } - case provider == "appmesh": + case provider == flaggerv1.AppMeshProvider: return &AppMeshRouter{ logger: factory.logger, flaggerClient: factory.flaggerClient, kubeClient: factory.kubeClient, appmeshClient: factory.meshClient, } - case strings.HasPrefix(provider, "smi:"): - mesh := strings.TrimPrefix(provider, "smi:") + case provider == flaggerv1.LinkerdProvider: return &SmiRouter{ logger: factory.logger, flaggerClient: factory.flaggerClient, kubeClient: factory.kubeClient, smiClient: factory.meshClient, - targetMesh: mesh, + targetMesh: flaggerv1.LinkerdProvider, + } + case provider == flaggerv1.IstioProvider: + return &IstioRouter{ + logger: factory.logger, + flaggerClient: factory.flaggerClient, + kubeClient: factory.kubeClient, + istioClient: factory.meshClient, } - case provider == "linkerd": + case strings.HasPrefix(provider, flaggerv1.SMIProvider): + mesh := strings.TrimPrefix(provider, flaggerv1.SMIProvider+":") return &SmiRouter{ logger: factory.logger, flaggerClient: factory.flaggerClient, kubeClient: factory.kubeClient, smiClient: factory.meshClient, - targetMesh: "linkerd", + targetMesh: mesh, } - case provider == "contour": + case provider == flaggerv1.ContourProvider: return &ContourRouter{ logger: factory.logger, flaggerClient: factory.flaggerClient, kubeClient: factory.kubeClient, contourClient: factory.meshClient, } - case strings.HasPrefix(provider, "gloo"): - upstreamDiscoveryNs := "gloo-system" - if strings.HasPrefix(provider, "gloo:") { - upstreamDiscoveryNs = strings.TrimPrefix(provider, "gloo:") + case strings.HasPrefix(provider, flaggerv1.GlooProvider): + upstreamDiscoveryNs := flaggerv1.GlooProvider + "-system" + if strings.HasPrefix(provider, flaggerv1.GlooProvider+":") { + upstreamDiscoveryNs = strings.TrimPrefix(provider, flaggerv1.GlooProvider+":") } return &GlooRouter{ logger: factory.logger, @@ -106,28 +112,14 @@ func (factory *Factory) MeshRouter(provider string) Interface { glooClient: factory.meshClient, upstreamDiscoveryNs: upstreamDiscoveryNs, } - case strings.HasPrefix(provider, "supergloo:appmesh"): - return &AppMeshRouter{ - logger: factory.logger, - flaggerClient: factory.flaggerClient, - kubeClient: factory.kubeClient, - appmeshClient: factory.meshClient, - } - case strings.HasPrefix(provider, "supergloo:istio"): - return &IstioRouter{ - logger: factory.logger, - flaggerClient: factory.flaggerClient, - kubeClient: factory.kubeClient, - istioClient: factory.meshClient, - } - case strings.HasPrefix(provider, "supergloo:linkerd"): - return &SmiRouter{ - logger: factory.logger, - flaggerClient: factory.flaggerClient, - kubeClient: factory.kubeClient, - smiClient: factory.meshClient, - targetMesh: "linkerd", + case provider == flaggerv1.NGINXProvider: + return &IngressRouter{ + logger: factory.logger, + kubeClient: factory.kubeClient, + annotationsPrefix: factory.ingressAnnotationsPrefix, } + case provider == flaggerv1.KubernetesProvider: + return &NopRouter{} default: return &IstioRouter{ logger: factory.logger, diff --git a/pkg/router/kubernetes_default.go b/pkg/router/kubernetes_default.go index a8d4a9c93..614f79aa4 100644 --- a/pkg/router/kubernetes_default.go +++ b/pkg/router/kubernetes_default.go @@ -181,7 +181,6 @@ func (c *KubernetesDefaultRouter) reconcileService(canary *flaggerv1.Canary, nam portsDiff := cmp.Diff(svcSpec.Ports, svc.Spec.Ports, cmpopts.SortSlices(sortPorts)) selectorsDiff := cmp.Diff(svcSpec.Selector, svc.Spec.Selector) - if portsDiff != "" || selectorsDiff != "" { svcClone.Spec.Ports = svcSpec.Ports svcClone.Spec.Selector = svcSpec.Selector @@ -191,11 +190,14 @@ func (c *KubernetesDefaultRouter) reconcileService(canary *flaggerv1.Canary, nam // update annotations and labels only if the service has been created by Flagger if _, owned := c.isOwnedByCanary(svc, canary.Name); owned { - if cmp.Diff(metadata.Annotations, svc.ObjectMeta.Annotations) != "" { + if svc.ObjectMeta.Annotations == nil { + svc.ObjectMeta.Annotations = make(map[string]string) + } + if diff := cmp.Diff(metadata.Annotations, svc.ObjectMeta.Annotations); diff != "" { svcClone.ObjectMeta.Annotations = metadata.Annotations updateService = true } - if cmp.Diff(metadata.Labels, svc.ObjectMeta.Labels) != "" { + if diff := cmp.Diff(metadata.Labels, svc.ObjectMeta.Labels); diff != "" { svcClone.ObjectMeta.Labels = metadata.Labels updateService = true }