Merge pull request #584 from weaveworks/appmesh-v1beta2

Implement AppMesh v1beta2 router
This commit is contained in:
Stefan Prodan
2020-05-14 09:38:08 +03:00
committed by GitHub
52 changed files with 5462 additions and 441 deletions
+2
View File
@@ -110,6 +110,8 @@ rules:
resources:
- virtualnodes
- virtualnodes/finalizers
- virtualrouters
- virtualrouters/finalizers
- virtualservices
- virtualservices/finalizers
verbs:
+2
View File
@@ -106,6 +106,8 @@ rules:
resources:
- virtualnodes
- virtualnodes/finalizers
- virtualrouters
- virtualrouters/finalizers
- virtualservices
- virtualservices/finalizers
verbs:
@@ -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
@@ -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
+1 -1
View File
@@ -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
+2
View File
@@ -100,6 +100,8 @@ rules:
resources:
- virtualnodes
- virtualnodes/finalizers
- virtualrouters
- virtualrouters/finalizers
- virtualservices
- virtualservices/finalizers
verbs:
+5
View File
@@ -0,0 +1,5 @@
// +k8s:deepcopy-gen=package
// Package v1beta2 is the v1beta2 version of the API.
// +groupName=appmesh.k8s.aws
package v1beta2
+41
View File
@@ -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
}
+91
View File
@@ -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"`
}
@@ -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"`
}
@@ -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"`
}
@@ -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"`
}
File diff suppressed because it is too large Load Diff
+12
View File
@@ -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"
)
@@ -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)
@@ -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}
@@ -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,
@@ -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,
@@ -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
}
@@ -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
@@ -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
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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{}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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)
@@ -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}
}
@@ -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())
}
@@ -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())
}
@@ -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())
}
@@ -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
@@ -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{}
@@ -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
}
@@ -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
}
@@ -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
}
+1 -1
View File
@@ -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)
}
+24 -9
View File
@@ -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
@@ -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,
@@ -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,
-77
View File
@@ -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
}
@@ -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
}
@@ -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)
}
-84
View File
@@ -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)
}
+14 -26
View File
@@ -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{
case provider == flaggerv1.LinkerdProvider:
return &LinkerdObserver{
client: factory.Client,
}
case provider == "nginx":
return &NginxObserver{
case provider == flaggerv1.IstioProvider:
return &IstioObserver{
client: factory.Client,
}
case strings.HasPrefix(provider, "gloo"):
case provider == flaggerv1.ContourProvider:
return &ContourObserver{
client: factory.Client,
}
case strings.HasPrefix(provider, flaggerv1.GlooProvider):
return &GlooObserver{
client: factory.Client,
}
case provider == "smi:linkerd":
return &LinkerdObserver{
case provider == flaggerv1.NGINXProvider:
return &NginxObserver{
client: factory.Client,
}
case provider == "crossover:service":
return &CrossoverServiceObserver{
client: factory.Client,
}
case provider == "linkerd":
return &LinkerdObserver{
client: factory.Client,
}
case provider == "contour":
return &ContourObserver{
case provider == flaggerv1.KubernetesProvider:
return &HttpObserver{
client: factory.Client,
}
default:
+540
View File
@@ -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
}
+162
View File
@@ -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)
}
+39 -47
View File
@@ -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,27 +52,40 @@ 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: flaggerv1.LinkerdProvider,
}
case provider == flaggerv1.IstioProvider:
return &IstioRouter{
logger: factory.logger,
flaggerClient: factory.flaggerClient,
kubeClient: factory.kubeClient,
istioClient: factory.meshClient,
}
case strings.HasPrefix(provider, flaggerv1.SMIProvider):
mesh := strings.TrimPrefix(provider, flaggerv1.SMIProvider+":")
return &SmiRouter{
logger: factory.logger,
flaggerClient: factory.flaggerClient,
@@ -79,25 +93,17 @@ func (factory *Factory) MeshRouter(provider string) Interface {
smiClient: factory.meshClient,
targetMesh: mesh,
}
case provider == "linkerd":
return &SmiRouter{
logger: factory.logger,
flaggerClient: factory.flaggerClient,
kubeClient: factory.kubeClient,
smiClient: factory.meshClient,
targetMesh: "linkerd",
}
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,
+5 -3
View File
@@ -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
}