mirror of
https://github.com/fluxcd/flagger.git
synced 2026-04-15 06:57:34 +00:00
Merge pull request #200 from weaveworks/traffic-policy
Add support for Istio traffic policy
This commit is contained in:
Generated
+4
@@ -1138,6 +1138,7 @@
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/gogo/protobuf/types",
|
||||
"github.com/google/go-cmp/cmp",
|
||||
"github.com/google/go-cmp/cmp/cmpopts",
|
||||
"github.com/prometheus/client_golang/prometheus",
|
||||
@@ -1146,9 +1147,11 @@
|
||||
"github.com/solo-io/solo-kit/pkg/api/v1/clients",
|
||||
"github.com/solo-io/solo-kit/pkg/api/v1/clients/factory",
|
||||
"github.com/solo-io/solo-kit/pkg/api/v1/clients/kube",
|
||||
"github.com/solo-io/solo-kit/pkg/api/v1/clients/kube/crd/solo.io/v1",
|
||||
"github.com/solo-io/solo-kit/pkg/api/v1/clients/memory",
|
||||
"github.com/solo-io/solo-kit/pkg/api/v1/resources/core",
|
||||
"github.com/solo-io/solo-kit/pkg/errors",
|
||||
"github.com/solo-io/supergloo/pkg/api/external/istio/networking/v1alpha3",
|
||||
"github.com/solo-io/supergloo/pkg/api/v1",
|
||||
"github.com/stefanprodan/klog",
|
||||
"go.uber.org/zap",
|
||||
@@ -1158,6 +1161,7 @@
|
||||
"k8s.io/api/autoscaling/v1",
|
||||
"k8s.io/api/autoscaling/v2beta1",
|
||||
"k8s.io/api/core/v1",
|
||||
"k8s.io/api/extensions/v1beta1",
|
||||
"k8s.io/apimachinery/pkg/api/errors",
|
||||
"k8s.io/apimachinery/pkg/api/resource",
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
[](https://github.com/weaveworks/flagger/releases)
|
||||
|
||||
Flagger is a Kubernetes operator that automates the promotion of canary deployments
|
||||
using Istio, App Mesh or NGINX routing for traffic shifting and Prometheus metrics for canary analysis.
|
||||
using Istio, App Mesh, NGINX or Gloo routing for traffic shifting and Prometheus metrics for canary analysis.
|
||||
The canary analysis can be extended with webhooks for running acceptance tests,
|
||||
load tests or any other custom validation.
|
||||
|
||||
@@ -149,16 +149,27 @@ For more details on how the canary analysis and promotion works please [read the
|
||||
|
||||
## Features
|
||||
|
||||
| Feature | Istio | App Mesh | SuperGloo | NGINX Ingress |
|
||||
| -------------------------------------------- | ------------------ | ------------------ |------------------ |------------------ |
|
||||
| Canary deployments (weighted traffic) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| A/B testing (headers and cookies filters) | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: |
|
||||
| Load testing | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Webhooks (custom acceptance tests) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request success rate check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request duration check (L7 metric) | :heavy_check_mark: | :heavy_minus_sign: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Custom promql checks | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Ingress gateway (CORS, retries and timeouts) | :heavy_check_mark: | :heavy_minus_sign: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Service Mesh Feature | Istio | App Mesh | SuperGloo |
|
||||
| -------------------------------------------- | ------------------ | ------------------ |------------------ |
|
||||
| Canary deployments (weighted traffic) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| A/B testing (headers and cookies filters) | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
||||
| Load testing | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Webhooks (acceptance testing) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request success rate check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request duration check (L7 metric) | :heavy_check_mark: | :heavy_minus_sign: | :heavy_check_mark: |
|
||||
| Custom promql checks | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Ingress gateway (CORS, retries and timeouts) | :heavy_check_mark: | :heavy_minus_sign: | :heavy_check_mark: |
|
||||
|
||||
| Ingress Controller Feature | NGINX | Gloo |
|
||||
| -------------------------------------------- | ------------------ | ------------------ |
|
||||
| Canary deployments (weighted traffic) | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| A/B testing (headers and cookies filters) | :heavy_check_mark: | :heavy_minus_sign: |
|
||||
| Load testing | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Webhooks (acceptance testing) | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request success rate check (L7 metric) | :heavy_minus_sign: | :heavy_check_mark: |
|
||||
| Request duration check (L7 metric) | :heavy_minus_sign: | :heavy_check_mark: |
|
||||
| Custom promql checks | :heavy_check_mark: | :heavy_check_mark: |
|
||||
|
||||
|
||||
## Roadmap
|
||||
|
||||
|
||||
@@ -27,6 +27,10 @@ spec:
|
||||
# Istio virtual service host names (optional)
|
||||
hosts:
|
||||
- app.istio.weavedx.com
|
||||
# Istio traffic policy (optional)
|
||||
trafficPolicy:
|
||||
loadBalancer:
|
||||
simple: LEAST_CONN
|
||||
# HTTP match conditions (optional)
|
||||
match:
|
||||
- uri:
|
||||
@@ -34,13 +38,8 @@ spec:
|
||||
# HTTP rewrite (optional)
|
||||
rewrite:
|
||||
uri: /
|
||||
# Envoy timeout and retry policy (optional)
|
||||
headers:
|
||||
request:
|
||||
add:
|
||||
x-envoy-upstream-rq-timeout-ms: "15000"
|
||||
x-envoy-max-retries: "10"
|
||||
x-envoy-retry-on: "gateway-error,connect-failure,refused-stream"
|
||||
# HTTP timeout (optional)
|
||||
timeout: 30s
|
||||
# promote the canary without analysing it (default false)
|
||||
skipAnalysis: false
|
||||
canaryAnalysis:
|
||||
@@ -54,7 +53,7 @@ spec:
|
||||
# canary increment step
|
||||
# percentage (0-100)
|
||||
stepWeight: 5
|
||||
# Istio Prometheus checks
|
||||
# Prometheus checks
|
||||
metrics:
|
||||
- name: request-success-rate
|
||||
# minimum req success rate (non 5xx responses)
|
||||
|
||||
@@ -48,6 +48,8 @@ rules:
|
||||
resources:
|
||||
- virtualservices
|
||||
- virtualservices/status
|
||||
- destinationrules
|
||||
- destinationrules/status
|
||||
verbs: ["*"]
|
||||
- apiGroups:
|
||||
- appmesh.k8s.aws
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: DestinationRule
|
||||
metadata:
|
||||
name: podinfo-canary
|
||||
namespace: test
|
||||
spec:
|
||||
host: podinfo-canary
|
||||
trafficPolicy:
|
||||
loadBalancer:
|
||||
consistentHash:
|
||||
httpCookie:
|
||||
name: user
|
||||
ttl: 0s
|
||||
@@ -9,7 +9,7 @@ spec:
|
||||
kind: Deployment
|
||||
name: podinfo
|
||||
minReplicas: 2
|
||||
maxReplicas: 3
|
||||
maxReplicas: 2
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: DestinationRule
|
||||
metadata:
|
||||
name: podinfo-primary
|
||||
namespace: test
|
||||
spec:
|
||||
host: podinfo-primary
|
||||
trafficPolicy:
|
||||
loadBalancer:
|
||||
consistentHash:
|
||||
httpCookie:
|
||||
name: user
|
||||
ttl: 0s
|
||||
@@ -9,7 +9,7 @@ spec:
|
||||
kind: Deployment
|
||||
name: podinfo-primary
|
||||
minReplicas: 2
|
||||
maxReplicas: 4
|
||||
maxReplicas: 2
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
|
||||
@@ -7,24 +7,17 @@ metadata:
|
||||
app: podinfo
|
||||
spec:
|
||||
gateways:
|
||||
- public-gateway.istio-system.svc.cluster.local
|
||||
- mesh
|
||||
- public-gateway.istio-system.svc.cluster.local
|
||||
hosts:
|
||||
- podinfo.istio.weavedx.com
|
||||
- podinfo
|
||||
- app.istio.weavedx.com
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: podinfo-primary
|
||||
port:
|
||||
number: 9898
|
||||
weight: 100
|
||||
weight: 50
|
||||
- destination:
|
||||
host: podinfo
|
||||
port:
|
||||
number: 9898
|
||||
weight: 0
|
||||
timeout: 10s
|
||||
retries:
|
||||
attempts: 3
|
||||
perTryTimeout: 2s
|
||||
host: podinfo-canary
|
||||
weight: 50
|
||||
timeout: 5s
|
||||
|
||||
@@ -44,6 +44,8 @@ rules:
|
||||
resources:
|
||||
- virtualservices
|
||||
- virtualservices/status
|
||||
- destinationrules
|
||||
- destinationrules/status
|
||||
verbs: ["*"]
|
||||
- apiGroups:
|
||||
- appmesh.k8s.aws
|
||||
|
||||
@@ -103,9 +103,9 @@ the Istio Virtual Service. The container port from the target deployment should
|
||||
|
||||
### Istio routing
|
||||
|
||||
Flagger creates an Istio Virtual Service based on the Canary service spec. The service configuration lets you expose
|
||||
an app inside or outside the mesh.
|
||||
You can also define HTTP match conditions, URI rewrite rules, CORS policies, timeout and retries.
|
||||
Flagger creates an Istio Virtual Service and Destination Rules based on the Canary service spec.
|
||||
The service configuration lets you expose an app inside or outside the mesh.
|
||||
You can also define traffic policies, HTTP match conditions, URI rewrite rules, CORS policies, timeout and retries.
|
||||
|
||||
The following spec exposes the `frontend` workload inside the mesh on `frontend.test.svc.cluster.local:9898`
|
||||
and outside the mesh on `frontend.example.com`. You'll have to specify an Istio ingress gateway for external hosts.
|
||||
@@ -129,6 +129,10 @@ spec:
|
||||
# Istio virtual service host names (optional)
|
||||
hosts:
|
||||
- frontend.example.com
|
||||
# Istio traffic policy (optional)
|
||||
trafficPolicy:
|
||||
loadBalancer:
|
||||
simple: LEAST_CONN
|
||||
# HTTP match conditions (optional)
|
||||
match:
|
||||
- uri:
|
||||
@@ -198,18 +202,40 @@ spec:
|
||||
route:
|
||||
- destination:
|
||||
host: podinfo-primary
|
||||
port:
|
||||
number: 9898
|
||||
weight: 100
|
||||
- destination:
|
||||
host: podinfo-canary
|
||||
port:
|
||||
number: 9898
|
||||
weight: 0
|
||||
```
|
||||
|
||||
Flagger keeps in sync the virtual service with the canary service spec. Any direct modification to the virtual
|
||||
service spec will be overwritten.
|
||||
For each destination in the virtual service a rule is generated:
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: DestinationRule
|
||||
metadata:
|
||||
name: frontend-primary
|
||||
namespace: test
|
||||
spec:
|
||||
host: frontend-primary
|
||||
trafficPolicy:
|
||||
loadBalancer:
|
||||
simple: LEAST_CONN
|
||||
---
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: DestinationRule
|
||||
metadata:
|
||||
name: frontend-canary
|
||||
namespace: test
|
||||
spec:
|
||||
host: frontend-canary
|
||||
trafficPolicy:
|
||||
loadBalancer:
|
||||
simple: LEAST_CONN
|
||||
```
|
||||
|
||||
Flagger keeps in sync the virtual service and destination rules with the canary service spec.
|
||||
Any direct modification to the virtual service spec will be overwritten.
|
||||
|
||||
To expose a workload inside the mesh on `http://backend.test.svc.cluster.local:9898`,
|
||||
the service spec can contain only the container port:
|
||||
|
||||
@@ -120,6 +120,8 @@ horizontalpodautoscaler.autoscaling/abtest-primary
|
||||
service/abtest
|
||||
service/abtest-canary
|
||||
service/abtest-primary
|
||||
destinationrule.networking.istio.io/abtest-canary
|
||||
destinationrule.networking.istio.io/abtest-primary
|
||||
virtualservice.networking.istio.io/abtest
|
||||
```
|
||||
|
||||
|
||||
@@ -108,6 +108,8 @@ horizontalpodautoscaler.autoscaling/podinfo-primary
|
||||
service/podinfo
|
||||
service/podinfo-canary
|
||||
service/podinfo-primary
|
||||
destinationrule.networking.istio.io/podinfo-canary
|
||||
destinationrule.networking.istio.io/podinfo-primary
|
||||
virtualservice.networking.istio.io/podinfo
|
||||
```
|
||||
|
||||
|
||||
@@ -115,17 +115,18 @@ type CanaryStatus struct {
|
||||
// CanaryService is used to create ClusterIP services
|
||||
// and Istio Virtual Service
|
||||
type CanaryService struct {
|
||||
Port int32 `json:"port"`
|
||||
PortName string `json:"portName,omitempty"`
|
||||
Match []istiov1alpha3.HTTPMatchRequest `json:"match,omitempty"`
|
||||
Rewrite *istiov1alpha3.HTTPRewrite `json:"rewrite,omitempty"`
|
||||
Timeout string `json:"timeout,omitempty"`
|
||||
Retries *istiov1alpha3.HTTPRetry `json:"retries,omitempty"`
|
||||
Headers *istiov1alpha3.Headers `json:"headers,omitempty"`
|
||||
CorsPolicy *istiov1alpha3.CorsPolicy `json:"corsPolicy,omitempty"`
|
||||
//Istio
|
||||
Gateways []string `json:"gateways,omitempty"`
|
||||
Hosts []string `json:"hosts,omitempty"`
|
||||
Port int32 `json:"port"`
|
||||
PortName string `json:"portName,omitempty"`
|
||||
Timeout string `json:"timeout,omitempty"`
|
||||
// Istio
|
||||
Gateways []string `json:"gateways,omitempty"`
|
||||
Hosts []string `json:"hosts,omitempty"`
|
||||
TrafficPolicy *istiov1alpha3.TrafficPolicy `json:"trafficPolicy,omitempty"`
|
||||
Match []istiov1alpha3.HTTPMatchRequest `json:"match,omitempty"`
|
||||
Rewrite *istiov1alpha3.HTTPRewrite `json:"rewrite,omitempty"`
|
||||
Retries *istiov1alpha3.HTTPRetry `json:"retries,omitempty"`
|
||||
Headers *istiov1alpha3.Headers `json:"headers,omitempty"`
|
||||
CorsPolicy *istiov1alpha3.CorsPolicy `json:"corsPolicy,omitempty"`
|
||||
// App Mesh
|
||||
MeshName string `json:"meshName,omitempty"`
|
||||
Backends []string `json:"backends,omitempty"`
|
||||
|
||||
@@ -141,6 +141,21 @@ func (in *CanaryMetric) DeepCopy() *CanaryMetric {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryService) DeepCopyInto(out *CanaryService) {
|
||||
*out = *in
|
||||
if in.Gateways != nil {
|
||||
in, out := &in.Gateways, &out.Gateways
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Hosts != nil {
|
||||
in, out := &in.Hosts, &out.Hosts
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.TrafficPolicy != nil {
|
||||
in, out := &in.TrafficPolicy, &out.TrafficPolicy
|
||||
*out = new(istiov1alpha3.TrafficPolicy)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Match != nil {
|
||||
in, out := &in.Match, &out.Match
|
||||
*out = make([]istiov1alpha3.HTTPMatchRequest, len(*in))
|
||||
@@ -168,16 +183,6 @@ func (in *CanaryService) DeepCopyInto(out *CanaryService) {
|
||||
*out = new(istiov1alpha3.CorsPolicy)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Gateways != nil {
|
||||
in, out := &in.Gateways, &out.Gateways
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Hosts != nil {
|
||||
in, out := &in.Hosts, &out.Hosts
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Backends != nil {
|
||||
in, out := &in.Backends, &out.Backends
|
||||
*out = make([]string, len(*in))
|
||||
|
||||
@@ -0,0 +1,532 @@
|
||||
// proto: https://github.com/istio/api/blob/master/networking/v1alpha3/destination_rule.pb.go
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// DestinationRule
|
||||
type DestinationRule struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Spec DestinationRuleSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// DestinationRule defines policies that apply to traffic intended for a
|
||||
// service after routing has occurred. These rules specify configuration
|
||||
// for load balancing, connection pool size from the sidecar, and outlier
|
||||
// detection settings to detect and evict unhealthy hosts from the load
|
||||
// balancing pool. For example, a simple load balancing policy for the
|
||||
// ratings service would look as follows:
|
||||
//
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: bookinfo-ratings
|
||||
// spec:
|
||||
// host: ratings.prod.svc.cluster.local
|
||||
// trafficPolicy:
|
||||
// loadBalancer:
|
||||
// simple: LEAST_CONN
|
||||
//
|
||||
//
|
||||
// Version specific policies can be specified by defining a named
|
||||
// subset and overriding the settings specified at the service level. The
|
||||
// following rule uses a round robin load balancing policy for all traffic
|
||||
// going to a subset named testversion that is composed of endpoints (e.g.,
|
||||
// pods) with labels (version:v3).
|
||||
//
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: bookinfo-ratings
|
||||
// spec:
|
||||
// host: ratings.prod.svc.cluster.local
|
||||
// trafficPolicy:
|
||||
// loadBalancer:
|
||||
// simple: LEAST_CONN
|
||||
// subsets:
|
||||
// - name: testversion
|
||||
// labels:
|
||||
// version: v3
|
||||
// trafficPolicy:
|
||||
// loadBalancer:
|
||||
// simple: ROUND_ROBIN
|
||||
//
|
||||
//
|
||||
// **Note:** Policies specified for subsets will not take effect until
|
||||
// a route rule explicitly sends traffic to this subset.
|
||||
//
|
||||
// Traffic policies can be customized to specific ports as well. The
|
||||
// following rule uses the least connection load balancing policy for all
|
||||
// traffic to port 80, while uses a round robin load balancing setting for
|
||||
// traffic to the port 9080.
|
||||
//
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: bookinfo-ratings-port
|
||||
// spec:
|
||||
// host: ratings.prod.svc.cluster.local
|
||||
// trafficPolicy: # Apply to all ports
|
||||
// portLevelSettings:
|
||||
// - port:
|
||||
// number: 80
|
||||
// loadBalancer:
|
||||
// simple: LEAST_CONN
|
||||
// - port:
|
||||
// number: 9080
|
||||
// loadBalancer:
|
||||
// simple: ROUND_ROBIN
|
||||
//
|
||||
type DestinationRuleSpec struct {
|
||||
// REQUIRED. The name of a service from the service registry. Service
|
||||
// names are looked up from the platform's service registry (e.g.,
|
||||
// Kubernetes services, Consul services, etc.) and from the hosts
|
||||
// declared by [ServiceEntries](#ServiceEntry). Rules defined for
|
||||
// services that do not exist in the service registry will be ignored.
|
||||
//
|
||||
// *Note for Kubernetes users*: When short names are used (e.g. "reviews"
|
||||
// instead of "reviews.default.svc.cluster.local"), Istio will interpret
|
||||
// the short name based on the namespace of the rule, not the service. A
|
||||
// rule in the "default" namespace containing a host "reviews will be
|
||||
// interpreted as "reviews.default.svc.cluster.local", irrespective of
|
||||
// the actual namespace associated with the reviews service. _To avoid
|
||||
// potential misconfigurations, it is recommended to always use fully
|
||||
// qualified domain names over short names._
|
||||
//
|
||||
// Note that the host field applies to both HTTP and TCP services.
|
||||
Host string `json:"host"`
|
||||
|
||||
// Traffic policies to apply (load balancing policy, connection pool
|
||||
// sizes, outlier detection).
|
||||
TrafficPolicy *TrafficPolicy `json:"trafficPolicy,omitempty"`
|
||||
|
||||
// One or more named sets that represent individual versions of a
|
||||
// service. Traffic policies can be overridden at subset level.
|
||||
Subsets []Subset `json:"subsets,omitempty"`
|
||||
}
|
||||
|
||||
// Traffic policies to apply for a specific destination, across all
|
||||
// destination ports. See DestinationRule for examples.
|
||||
type TrafficPolicy struct {
|
||||
|
||||
// Settings controlling the load balancer algorithms.
|
||||
LoadBalancer *LoadBalancerSettings `json:"loadBalancer,omitempty"`
|
||||
|
||||
// Settings controlling the volume of connections to an upstream service
|
||||
ConnectionPool *ConnectionPoolSettings `json:"connectionPool,omitempty"`
|
||||
|
||||
// Settings controlling eviction of unhealthy hosts from the load balancing pool
|
||||
OutlierDetection *OutlierDetection `json:"outlierDetection,omitempty"`
|
||||
|
||||
// TLS related settings for connections to the upstream service.
|
||||
TLS *TLSSettings `json:"tls,omitempty"`
|
||||
|
||||
// Traffic policies specific to individual ports. Note that port level
|
||||
// settings will override the destination-level settings. Traffic
|
||||
// settings specified at the destination-level will not be inherited when
|
||||
// overridden by port-level settings, i.e. default values will be applied
|
||||
// to fields omitted in port-level traffic policies.
|
||||
PortLevelSettings []PortTrafficPolicy `json:"portLevelSettings,omitempty"`
|
||||
}
|
||||
|
||||
// Traffic policies that apply to specific ports of the service
|
||||
type PortTrafficPolicy struct {
|
||||
// Specifies the port name or number of a port on the destination service
|
||||
// on which this policy is being applied.
|
||||
//
|
||||
// Names must comply with DNS label syntax (rfc1035) and therefore cannot
|
||||
// collide with numbers. If there are multiple ports on a service with
|
||||
// the same protocol the names should be of the form <protocol-name>-<DNS
|
||||
// label>.
|
||||
Port PortSelector `json:"port"`
|
||||
|
||||
// Settings controlling the load balancer algorithms.
|
||||
LoadBalancer *LoadBalancerSettings `json:"loadBalancer,omitempty"`
|
||||
|
||||
// Settings controlling the volume of connections to an upstream service
|
||||
ConnectionPool *ConnectionPoolSettings `json:"connectionPool,omitempty"`
|
||||
|
||||
// Settings controlling eviction of unhealthy hosts from the load balancing pool
|
||||
OutlierDetection *OutlierDetection `json:"outlierDetection,omitempty"`
|
||||
|
||||
// TLS related settings for connections to the upstream service.
|
||||
TLS *TLSSettings `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// A subset of endpoints of a service. Subsets can be used for scenarios
|
||||
// like A/B testing, or routing to a specific version of a service. Refer
|
||||
// to [VirtualService](#VirtualService) documentation for examples of using
|
||||
// subsets in these scenarios. In addition, traffic policies defined at the
|
||||
// service-level can be overridden at a subset-level. The following rule
|
||||
// uses a round robin load balancing policy for all traffic going to a
|
||||
// subset named testversion that is composed of endpoints (e.g., pods) with
|
||||
// labels (version:v3).
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: bookinfo-ratings
|
||||
// spec:
|
||||
// host: ratings.prod.svc.cluster.local
|
||||
// trafficPolicy:
|
||||
// loadBalancer:
|
||||
// simple: LEAST_CONN
|
||||
// subsets:
|
||||
// - name: testversion
|
||||
// labels:
|
||||
// version: v3
|
||||
// trafficPolicy:
|
||||
// loadBalancer:
|
||||
// simple: ROUND_ROBIN
|
||||
//
|
||||
// **Note:** Policies specified for subsets will not take effect until
|
||||
// a route rule explicitly sends traffic to this subset.
|
||||
type Subset struct {
|
||||
// REQUIRED. Name of the subset. The service name and the subset name can
|
||||
// be used for traffic splitting in a route rule.
|
||||
Name string `json:"name"`
|
||||
|
||||
// REQUIRED. Labels apply a filter over the endpoints of a service in the
|
||||
// service registry. See route rules for examples of usage.
|
||||
Labels map[string]string `json:"labels"`
|
||||
|
||||
// Traffic policies that apply to this subset. Subsets inherit the
|
||||
// traffic policies specified at the DestinationRule level. Settings
|
||||
// specified at the subset level will override the corresponding settings
|
||||
// specified at the DestinationRule level.
|
||||
TrafficPolicy *TrafficPolicy `json:"trafficPolicy,omitempty"`
|
||||
}
|
||||
|
||||
// Load balancing policies to apply for a specific destination. See Envoy's
|
||||
// load balancing
|
||||
// [documentation](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/load_balancing.html)
|
||||
// for more details.
|
||||
//
|
||||
// For example, the following rule uses a round robin load balancing policy
|
||||
// for all traffic going to the ratings service.
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: bookinfo-ratings
|
||||
// spec:
|
||||
// host: ratings.prod.svc.cluster.local
|
||||
// trafficPolicy:
|
||||
// loadBalancer:
|
||||
// simple: ROUND_ROBIN
|
||||
//
|
||||
// The following example sets up sticky sessions for the ratings service
|
||||
// hashing-based load balancer for the same ratings service using the
|
||||
// the User cookie as the hash key.
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: bookinfo-ratings
|
||||
// spec:
|
||||
// host: ratings.prod.svc.cluster.local
|
||||
// trafficPolicy:
|
||||
// loadBalancer:
|
||||
// consistentHash:
|
||||
// httpCookie:
|
||||
// name: user
|
||||
// ttl: 0s
|
||||
type LoadBalancerSettings struct {
|
||||
// It is required to specify exactly one of the fields:
|
||||
// Simple or ConsistentHash
|
||||
Simple SimpleLB `json:"simple,omitempty"`
|
||||
ConsistentHash *ConsistentHashLB `json:"consistentHash,omitempty"`
|
||||
}
|
||||
|
||||
// Standard load balancing algorithms that require no tuning.
|
||||
type SimpleLB string
|
||||
|
||||
const (
|
||||
// Round Robin policy. Default
|
||||
SimpleLBRoundRobin SimpleLB = "ROUND_ROBIN"
|
||||
|
||||
// The least request load balancer uses an O(1) algorithm which selects
|
||||
// two random healthy hosts and picks the host which has fewer active
|
||||
// requests.
|
||||
SimpleLBLeastConn SimpleLB = "LEAST_CONN"
|
||||
|
||||
// The random load balancer selects a random healthy host. The random
|
||||
// load balancer generally performs better than round robin if no health
|
||||
// checking policy is configured.
|
||||
SimpleLBRandom SimpleLB = "RANDOM"
|
||||
|
||||
// This option will forward the connection to the original IP address
|
||||
// requested by the caller without doing any form of load
|
||||
// balancing. This option must be used with care. It is meant for
|
||||
// advanced use cases. Refer to Original Destination load balancer in
|
||||
// Envoy for further details.
|
||||
SimpleLBPassthrough SimpleLB = "PASSTHROUGH"
|
||||
)
|
||||
|
||||
// Consistent Hash-based load balancing can be used to provide soft
|
||||
// session affinity based on HTTP headers, cookies or other
|
||||
// properties. This load balancing policy is applicable only for HTTP
|
||||
// connections. The affinity to a particular destination host will be
|
||||
// lost when one or more hosts are added/removed from the destination
|
||||
// service.
|
||||
type ConsistentHashLB struct {
|
||||
|
||||
// It is required to specify exactly one of the fields as hash key:
|
||||
// HTTPHeaderName, HTTPCookie, or UseSourceIP.
|
||||
// Hash based on a specific HTTP header.
|
||||
HTTPHeaderName string `json:"httpHeaderName,omitempty"`
|
||||
|
||||
// Hash based on HTTP cookie.
|
||||
HTTPCookie *HTTPCookie `json:"httpCookie,omitempty"`
|
||||
|
||||
// Hash based on the source IP address.
|
||||
UseSourceIP bool `json:"useSourceIp,omitempty"`
|
||||
|
||||
// The minimum number of virtual nodes to use for the hash
|
||||
// ring. Defaults to 1024. Larger ring sizes result in more granular
|
||||
// load distributions. If the number of hosts in the load balancing
|
||||
// pool is larger than the ring size, each host will be assigned a
|
||||
// single virtual node.
|
||||
MinimumRingSize uint64 `json:"minimumRingSize,omitempty"`
|
||||
}
|
||||
|
||||
// Describes a HTTP cookie that will be used as the hash key for the
|
||||
// Consistent Hash load balancer. If the cookie is not present, it will
|
||||
// be generated.
|
||||
type HTTPCookie struct {
|
||||
// REQUIRED. Name of the cookie.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Path to set for the cookie.
|
||||
Path string `json:"path,omitempty"`
|
||||
|
||||
// REQUIRED. Lifetime of the cookie.
|
||||
TTL string `json:"ttl"`
|
||||
}
|
||||
|
||||
// Connection pool settings for an upstream host. The settings apply to
|
||||
// each individual host in the upstream service. See Envoy's [circuit
|
||||
// breaker](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/circuit_breaking)
|
||||
// for more details. Connection pool settings can be applied at the TCP
|
||||
// level as well as at HTTP level.
|
||||
//
|
||||
// For example, the following rule sets a limit of 100 connections to redis
|
||||
// service called myredissrv with a connect timeout of 30ms
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: bookinfo-redis
|
||||
// spec:
|
||||
// host: myredissrv.prod.svc.cluster.local
|
||||
// trafficPolicy:
|
||||
// connectionPool:
|
||||
// tcp:
|
||||
// maxConnections: 100
|
||||
// connectTimeout: 30ms
|
||||
type ConnectionPoolSettings struct {
|
||||
|
||||
// Settings common to both HTTP and TCP upstream connections.
|
||||
TCP *TCPSettings `json:"tcp,omitempty"`
|
||||
|
||||
// HTTP connection pool settings.
|
||||
HTTP *HTTPSettings `json:"http,omitempty"`
|
||||
}
|
||||
|
||||
// Settings common to both HTTP and TCP upstream connections.
|
||||
type TCPSettings struct {
|
||||
// Maximum number of HTTP1 /TCP connections to a destination host.
|
||||
MaxConnections int32 `json:"maxConnections,omitempty"`
|
||||
|
||||
// TCP connection timeout.
|
||||
ConnectTimeout string `json:"connectTimeout,omitempty"`
|
||||
}
|
||||
|
||||
// Settings applicable to HTTP1.1/HTTP2/GRPC connections.
|
||||
type HTTPSettings struct {
|
||||
// Maximum number of pending HTTP requests to a destination. Default 1024.
|
||||
HTTP1MaxPendingRequests int32 `json:"http1MaxPendingRequests,omitempty"`
|
||||
|
||||
// Maximum number of requests to a backend. Default 1024.
|
||||
HTTP2MaxRequests int32 `json:"http2MaxRequests,omitempty"`
|
||||
|
||||
// Maximum number of requests per connection to a backend. Setting this
|
||||
// parameter to 1 disables keep alive.
|
||||
MaxRequestsPerConnection int32 `json:"maxRequestsPerConnection,omitempty"`
|
||||
|
||||
// Maximum number of retries that can be outstanding to all hosts in a
|
||||
// cluster at a given time. Defaults to 3.
|
||||
MaxRetries int32 `json:"maxRetries,omitempty"`
|
||||
}
|
||||
|
||||
// A Circuit breaker implementation that tracks the status of each
|
||||
// individual host in the upstream service. Applicable to both HTTP and
|
||||
// TCP services. For HTTP services, hosts that continually return 5xx
|
||||
// errors for API calls are ejected from the pool for a pre-defined period
|
||||
// of time. For TCP services, connection timeouts or connection
|
||||
// failures to a given host counts as an error when measuring the
|
||||
// consecutive errors metric. See Envoy's [outlier
|
||||
// detection](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/outlier)
|
||||
// for more details.
|
||||
//
|
||||
// The following rule sets a connection pool size of 100 connections and
|
||||
// 1000 concurrent HTTP2 requests, with no more than 10 req/connection to
|
||||
// "reviews" service. In addition, it configures upstream hosts to be
|
||||
// scanned every 5 mins, such that any host that fails 7 consecutive times
|
||||
// with 5XX error code will be ejected for 15 minutes.
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: reviews-cb-policy
|
||||
// spec:
|
||||
// host: reviews.prod.svc.cluster.local
|
||||
// trafficPolicy:
|
||||
// connectionPool:
|
||||
// tcp:
|
||||
// maxConnections: 100
|
||||
// http:
|
||||
// http2MaxRequests: 1000
|
||||
// maxRequestsPerConnection: 10
|
||||
// outlierDetection:
|
||||
// consecutiveErrors: 7
|
||||
// interval: 5m
|
||||
// baseEjectionTime: 15m
|
||||
type OutlierDetection struct {
|
||||
// Number of errors before a host is ejected from the connection
|
||||
// pool. Defaults to 5. When the upstream host is accessed over HTTP, a
|
||||
// 5xx return code qualifies as an error. When the upstream host is
|
||||
// accessed over an opaque TCP connection, connect timeouts and
|
||||
// connection error/failure events qualify as an error.
|
||||
ConsecutiveErrors int32 `json:"consecutiveErrors,omitempty"`
|
||||
|
||||
// Time interval between ejection sweep analysis. format:
|
||||
// 1h/1m/1s/1ms. MUST BE >=1ms. Default is 10s.
|
||||
Interval string `json:"interval,omitempty"`
|
||||
|
||||
// Minimum ejection duration. A host will remain ejected for a period
|
||||
// equal to the product of minimum ejection duration and the number of
|
||||
// times the host has been ejected. This technique allows the system to
|
||||
// automatically increase the ejection period for unhealthy upstream
|
||||
// servers. format: 1h/1m/1s/1ms. MUST BE >=1ms. Default is 30s.
|
||||
BaseEjectionTime string `json:"baseEjectionTime,omitempty"`
|
||||
|
||||
// Maximum % of hosts in the load balancing pool for the upstream
|
||||
// service that can be ejected. Defaults to 10%.
|
||||
MaxEjectionPercent int32 `json:"maxEjectionPercent,omitempty"`
|
||||
}
|
||||
|
||||
// SSL/TLS related settings for upstream connections. See Envoy's [TLS
|
||||
// context](https://www.envoyproxy.io/docs/envoy/latest/api-v1/cluster_manager/cluster_ssl.html#config-cluster-manager-cluster-ssl)
|
||||
// for more details. These settings are common to both HTTP and TCP upstreams.
|
||||
//
|
||||
// For example, the following rule configures a client to use mutual TLS
|
||||
// for connections to upstream database cluster.
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: db-mtls
|
||||
// spec:
|
||||
// host: mydbserver.prod.svc.cluster.local
|
||||
// trafficPolicy:
|
||||
// tls:
|
||||
// mode: MUTUAL
|
||||
// clientCertificate: /etc/certs/myclientcert.pem
|
||||
// privateKey: /etc/certs/client_private_key.pem
|
||||
// caCertificates: /etc/certs/rootcacerts.pem
|
||||
//
|
||||
// The following rule configures a client to use TLS when talking to a
|
||||
// foreign service whose domain matches *.foo.com.
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: tls-foo
|
||||
// spec:
|
||||
// host: "*.foo.com"
|
||||
// trafficPolicy:
|
||||
// tls:
|
||||
// mode: SIMPLE
|
||||
//
|
||||
// The following rule configures a client to use Istio mutual TLS when talking
|
||||
// to rating services.
|
||||
//
|
||||
// apiVersion: networking.istio.io/v1alpha3
|
||||
// kind: DestinationRule
|
||||
// metadata:
|
||||
// name: ratings-istio-mtls
|
||||
// spec:
|
||||
// host: ratings.prod.svc.cluster.local
|
||||
// trafficPolicy:
|
||||
// tls:
|
||||
// mode: ISTIO_MUTUAL
|
||||
type TLSSettings struct {
|
||||
|
||||
// REQUIRED: Indicates whether connections to this port should be secured
|
||||
// using TLS. The value of this field determines how TLS is enforced.
|
||||
Mode TLSmode `json:"mode"`
|
||||
|
||||
// REQUIRED if mode is `MUTUAL`. The path to the file holding the
|
||||
// client-side TLS certificate to use.
|
||||
// Should be empty if mode is `ISTIO_MUTUAL`.
|
||||
ClientCertificate string `json:"clientCertificate,omitempty"`
|
||||
|
||||
// REQUIRED if mode is `MUTUAL`. The path to the file holding the
|
||||
// client's private key.
|
||||
// Should be empty if mode is `ISTIO_MUTUAL`.
|
||||
PrivateKey string `json:"privateKey,omitempty"`
|
||||
|
||||
// OPTIONAL: The path to the file containing certificate authority
|
||||
// certificates to use in verifying a presented server certificate. If
|
||||
// omitted, the proxy will not verify the server's certificate.
|
||||
// Should be empty if mode is `ISTIO_MUTUAL`.
|
||||
CaCertificates string `json:"caCertificates,omitempty"`
|
||||
|
||||
// A list of alternate names to verify the subject identity in the
|
||||
// certificate. If specified, the proxy will verify that the server
|
||||
// certificate's subject alt name matches one of the specified values.
|
||||
// Should be empty if mode is `ISTIO_MUTUAL`.
|
||||
SubjectAltNames []string `json:"subjectAltNames,omitempty"`
|
||||
|
||||
// SNI string to present to the server during TLS handshake.
|
||||
// Should be empty if mode is `ISTIO_MUTUAL`.
|
||||
Sni string `json:"sni,omitempty"`
|
||||
}
|
||||
|
||||
// TLS connection mode
|
||||
type TLSmode string
|
||||
|
||||
const (
|
||||
// Do not setup a TLS connection to the upstream endpoint.
|
||||
TLSmodeDisable TLSmode = "DISABLE"
|
||||
|
||||
// Originate a TLS connection to the upstream endpoint.
|
||||
TLSmodeSimple TLSmode = "SIMPLE"
|
||||
|
||||
// Secure connections to the upstream using mutual TLS by presenting
|
||||
// client certificates for authentication.
|
||||
TLSmodeMutual TLSmode = "MUTUAL"
|
||||
|
||||
// Secure connections to the upstream using mutual TLS by presenting
|
||||
// client certificates for authentication.
|
||||
// Compared to Mutual mode, this mode uses certificates generated
|
||||
// automatically by Istio for mTLS authentication. When this mode is
|
||||
// used, all other fields in `TLSSettings` should be empty.
|
||||
TLSmodeIstioMutual TLSmode = "ISTIO_MUTUAL"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// DestinationRuleList is a list of DestinationRule resources
|
||||
type DestinationRuleList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
Items []DestinationRule `json:"items"`
|
||||
}
|
||||
@@ -30,6 +30,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&VirtualService{},
|
||||
&VirtualServiceList{},
|
||||
&DestinationRule{},
|
||||
&DestinationRuleList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
|
||||
@@ -280,7 +280,7 @@ type Destination struct {
|
||||
// Specifies the port on the host that is being addressed. If a service
|
||||
// exposes only a single port it is not required to explicitly select the
|
||||
// port.
|
||||
Port PortSelector `json:"port,omitempty"`
|
||||
Port *PortSelector `json:"port,omitempty"`
|
||||
}
|
||||
|
||||
// Describes match conditions and actions for routing HTTP/1.1, HTTP2, and
|
||||
|
||||
@@ -25,6 +25,53 @@ import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ConnectionPoolSettings) DeepCopyInto(out *ConnectionPoolSettings) {
|
||||
*out = *in
|
||||
if in.TCP != nil {
|
||||
in, out := &in.TCP, &out.TCP
|
||||
*out = new(TCPSettings)
|
||||
**out = **in
|
||||
}
|
||||
if in.HTTP != nil {
|
||||
in, out := &in.HTTP, &out.HTTP
|
||||
*out = new(HTTPSettings)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectionPoolSettings.
|
||||
func (in *ConnectionPoolSettings) DeepCopy() *ConnectionPoolSettings {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ConnectionPoolSettings)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ConsistentHashLB) DeepCopyInto(out *ConsistentHashLB) {
|
||||
*out = *in
|
||||
if in.HTTPCookie != nil {
|
||||
in, out := &in.HTTPCookie, &out.HTTPCookie
|
||||
*out = new(HTTPCookie)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsistentHashLB.
|
||||
func (in *ConsistentHashLB) DeepCopy() *ConsistentHashLB {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ConsistentHashLB)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CorsPolicy) DeepCopyInto(out *CorsPolicy) {
|
||||
*out = *in
|
||||
@@ -64,7 +111,11 @@ func (in *CorsPolicy) DeepCopy() *CorsPolicy {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Destination) DeepCopyInto(out *Destination) {
|
||||
*out = *in
|
||||
out.Port = in.Port
|
||||
if in.Port != nil {
|
||||
in, out := &in.Port, &out.Port
|
||||
*out = new(PortSelector)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -78,10 +129,98 @@ func (in *Destination) DeepCopy() *Destination {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DestinationRule) DeepCopyInto(out *DestinationRule) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationRule.
|
||||
func (in *DestinationRule) DeepCopy() *DestinationRule {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DestinationRule)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *DestinationRule) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DestinationRuleList) DeepCopyInto(out *DestinationRuleList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]DestinationRule, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationRuleList.
|
||||
func (in *DestinationRuleList) DeepCopy() *DestinationRuleList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DestinationRuleList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *DestinationRuleList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DestinationRuleSpec) DeepCopyInto(out *DestinationRuleSpec) {
|
||||
*out = *in
|
||||
if in.TrafficPolicy != nil {
|
||||
in, out := &in.TrafficPolicy, &out.TrafficPolicy
|
||||
*out = new(TrafficPolicy)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Subsets != nil {
|
||||
in, out := &in.Subsets, &out.Subsets
|
||||
*out = make([]Subset, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationRuleSpec.
|
||||
func (in *DestinationRuleSpec) DeepCopy() *DestinationRuleSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DestinationRuleSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DestinationWeight) DeepCopyInto(out *DestinationWeight) {
|
||||
*out = *in
|
||||
out.Destination = in.Destination
|
||||
in.Destination.DeepCopyInto(&out.Destination)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -95,6 +234,22 @@ func (in *DestinationWeight) DeepCopy() *DestinationWeight {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HTTPCookie) DeepCopyInto(out *HTTPCookie) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPCookie.
|
||||
func (in *HTTPCookie) DeepCopy() *HTTPCookie {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HTTPCookie)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HTTPFaultInjection) DeepCopyInto(out *HTTPFaultInjection) {
|
||||
*out = *in
|
||||
@@ -237,7 +392,9 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
|
||||
if in.Route != nil {
|
||||
in, out := &in.Route, &out.Route
|
||||
*out = make([]DestinationWeight, len(*in))
|
||||
copy(*out, *in)
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Redirect != nil {
|
||||
in, out := &in.Redirect, &out.Redirect
|
||||
@@ -262,7 +419,7 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
|
||||
if in.Mirror != nil {
|
||||
in, out := &in.Mirror, &out.Mirror
|
||||
*out = new(Destination)
|
||||
**out = **in
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.CorsPolicy != nil {
|
||||
in, out := &in.CorsPolicy, &out.CorsPolicy
|
||||
@@ -301,6 +458,22 @@ func (in *HTTPRoute) DeepCopy() *HTTPRoute {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HTTPSettings) DeepCopyInto(out *HTTPSettings) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPSettings.
|
||||
func (in *HTTPSettings) DeepCopy() *HTTPSettings {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HTTPSettings)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HeaderOperations) DeepCopyInto(out *HeaderOperations) {
|
||||
*out = *in
|
||||
@@ -422,6 +595,43 @@ func (in *L4MatchAttributes) DeepCopy() *L4MatchAttributes {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LoadBalancerSettings) DeepCopyInto(out *LoadBalancerSettings) {
|
||||
*out = *in
|
||||
if in.ConsistentHash != nil {
|
||||
in, out := &in.ConsistentHash, &out.ConsistentHash
|
||||
*out = new(ConsistentHashLB)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancerSettings.
|
||||
func (in *LoadBalancerSettings) DeepCopy() *LoadBalancerSettings {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LoadBalancerSettings)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OutlierDetection) DeepCopyInto(out *OutlierDetection) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OutlierDetection.
|
||||
func (in *OutlierDetection) DeepCopy() *OutlierDetection {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OutlierDetection)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PortSelector) DeepCopyInto(out *PortSelector) {
|
||||
*out = *in
|
||||
@@ -438,6 +648,71 @@ func (in *PortSelector) DeepCopy() *PortSelector {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PortTrafficPolicy) DeepCopyInto(out *PortTrafficPolicy) {
|
||||
*out = *in
|
||||
out.Port = in.Port
|
||||
if in.LoadBalancer != nil {
|
||||
in, out := &in.LoadBalancer, &out.LoadBalancer
|
||||
*out = new(LoadBalancerSettings)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ConnectionPool != nil {
|
||||
in, out := &in.ConnectionPool, &out.ConnectionPool
|
||||
*out = new(ConnectionPoolSettings)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.OutlierDetection != nil {
|
||||
in, out := &in.OutlierDetection, &out.OutlierDetection
|
||||
*out = new(OutlierDetection)
|
||||
**out = **in
|
||||
}
|
||||
if in.TLS != nil {
|
||||
in, out := &in.TLS, &out.TLS
|
||||
*out = new(TLSSettings)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortTrafficPolicy.
|
||||
func (in *PortTrafficPolicy) DeepCopy() *PortTrafficPolicy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PortTrafficPolicy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Subset) DeepCopyInto(out *Subset) {
|
||||
*out = *in
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.TrafficPolicy != nil {
|
||||
in, out := &in.TrafficPolicy, &out.TrafficPolicy
|
||||
*out = new(TrafficPolicy)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subset.
|
||||
func (in *Subset) DeepCopy() *Subset {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Subset)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TCPRoute) DeepCopyInto(out *TCPRoute) {
|
||||
*out = *in
|
||||
@@ -448,7 +723,7 @@ func (in *TCPRoute) DeepCopyInto(out *TCPRoute) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
out.Route = in.Route
|
||||
in.Route.DeepCopyInto(&out.Route)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -462,6 +737,86 @@ func (in *TCPRoute) DeepCopy() *TCPRoute {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TCPSettings) DeepCopyInto(out *TCPSettings) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPSettings.
|
||||
func (in *TCPSettings) DeepCopy() *TCPSettings {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TCPSettings)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TLSSettings) DeepCopyInto(out *TLSSettings) {
|
||||
*out = *in
|
||||
if in.SubjectAltNames != nil {
|
||||
in, out := &in.SubjectAltNames, &out.SubjectAltNames
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSSettings.
|
||||
func (in *TLSSettings) DeepCopy() *TLSSettings {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TLSSettings)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TrafficPolicy) DeepCopyInto(out *TrafficPolicy) {
|
||||
*out = *in
|
||||
if in.LoadBalancer != nil {
|
||||
in, out := &in.LoadBalancer, &out.LoadBalancer
|
||||
*out = new(LoadBalancerSettings)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ConnectionPool != nil {
|
||||
in, out := &in.ConnectionPool, &out.ConnectionPool
|
||||
*out = new(ConnectionPoolSettings)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.OutlierDetection != nil {
|
||||
in, out := &in.OutlierDetection, &out.OutlierDetection
|
||||
*out = new(OutlierDetection)
|
||||
**out = **in
|
||||
}
|
||||
if in.TLS != nil {
|
||||
in, out := &in.TLS, &out.TLS
|
||||
*out = new(TLSSettings)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.PortLevelSettings != nil {
|
||||
in, out := &in.PortLevelSettings, &out.PortLevelSettings
|
||||
*out = make([]PortTrafficPolicy, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficPolicy.
|
||||
func (in *TrafficPolicy) DeepCopy() *TrafficPolicy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TrafficPolicy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *VirtualService) DeepCopyInto(out *VirtualService) {
|
||||
*out = *in
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
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 v1alpha3
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
v1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3"
|
||||
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"
|
||||
)
|
||||
|
||||
// DestinationRulesGetter has a method to return a DestinationRuleInterface.
|
||||
// A group's client should implement this interface.
|
||||
type DestinationRulesGetter interface {
|
||||
DestinationRules(namespace string) DestinationRuleInterface
|
||||
}
|
||||
|
||||
// DestinationRuleInterface has methods to work with DestinationRule resources.
|
||||
type DestinationRuleInterface interface {
|
||||
Create(*v1alpha3.DestinationRule) (*v1alpha3.DestinationRule, error)
|
||||
Update(*v1alpha3.DestinationRule) (*v1alpha3.DestinationRule, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v1alpha3.DestinationRule, error)
|
||||
List(opts v1.ListOptions) (*v1alpha3.DestinationRuleList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha3.DestinationRule, err error)
|
||||
DestinationRuleExpansion
|
||||
}
|
||||
|
||||
// destinationRules implements DestinationRuleInterface
|
||||
type destinationRules struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newDestinationRules returns a DestinationRules
|
||||
func newDestinationRules(c *NetworkingV1alpha3Client, namespace string) *destinationRules {
|
||||
return &destinationRules{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the destinationRule, and returns the corresponding destinationRule object, and an error if there is any.
|
||||
func (c *destinationRules) Get(name string, options v1.GetOptions) (result *v1alpha3.DestinationRule, err error) {
|
||||
result = &v1alpha3.DestinationRule{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("destinationrules").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of DestinationRules that match those selectors.
|
||||
func (c *destinationRules) List(opts v1.ListOptions) (result *v1alpha3.DestinationRuleList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1alpha3.DestinationRuleList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("destinationrules").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested destinationRules.
|
||||
func (c *destinationRules) Watch(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("destinationrules").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a destinationRule and creates it. Returns the server's representation of the destinationRule, and an error, if there is any.
|
||||
func (c *destinationRules) Create(destinationRule *v1alpha3.DestinationRule) (result *v1alpha3.DestinationRule, err error) {
|
||||
result = &v1alpha3.DestinationRule{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("destinationrules").
|
||||
Body(destinationRule).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a destinationRule and updates it. Returns the server's representation of the destinationRule, and an error, if there is any.
|
||||
func (c *destinationRules) Update(destinationRule *v1alpha3.DestinationRule) (result *v1alpha3.DestinationRule, err error) {
|
||||
result = &v1alpha3.DestinationRule{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("destinationrules").
|
||||
Name(destinationRule.Name).
|
||||
Body(destinationRule).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the destinationRule and deletes it. Returns an error if one occurs.
|
||||
func (c *destinationRules) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("destinationrules").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *destinationRules) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOptions.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("destinationrules").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched destinationRule.
|
||||
func (c *destinationRules) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha3.DestinationRule, err error) {
|
||||
result = &v1alpha3.DestinationRule{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("destinationrules").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
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 (
|
||||
v1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3"
|
||||
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"
|
||||
)
|
||||
|
||||
// FakeDestinationRules implements DestinationRuleInterface
|
||||
type FakeDestinationRules struct {
|
||||
Fake *FakeNetworkingV1alpha3
|
||||
ns string
|
||||
}
|
||||
|
||||
var destinationrulesResource = schema.GroupVersionResource{Group: "networking.istio.io", Version: "v1alpha3", Resource: "destinationrules"}
|
||||
|
||||
var destinationrulesKind = schema.GroupVersionKind{Group: "networking.istio.io", Version: "v1alpha3", Kind: "DestinationRule"}
|
||||
|
||||
// Get takes name of the destinationRule, and returns the corresponding destinationRule object, and an error if there is any.
|
||||
func (c *FakeDestinationRules) Get(name string, options v1.GetOptions) (result *v1alpha3.DestinationRule, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(destinationrulesResource, c.ns, name), &v1alpha3.DestinationRule{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.DestinationRule), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of DestinationRules that match those selectors.
|
||||
func (c *FakeDestinationRules) List(opts v1.ListOptions) (result *v1alpha3.DestinationRuleList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(destinationrulesResource, destinationrulesKind, c.ns, opts), &v1alpha3.DestinationRuleList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha3.DestinationRuleList{ListMeta: obj.(*v1alpha3.DestinationRuleList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha3.DestinationRuleList).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 destinationRules.
|
||||
func (c *FakeDestinationRules) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(destinationrulesResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a destinationRule and creates it. Returns the server's representation of the destinationRule, and an error, if there is any.
|
||||
func (c *FakeDestinationRules) Create(destinationRule *v1alpha3.DestinationRule) (result *v1alpha3.DestinationRule, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(destinationrulesResource, c.ns, destinationRule), &v1alpha3.DestinationRule{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.DestinationRule), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a destinationRule and updates it. Returns the server's representation of the destinationRule, and an error, if there is any.
|
||||
func (c *FakeDestinationRules) Update(destinationRule *v1alpha3.DestinationRule) (result *v1alpha3.DestinationRule, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(destinationrulesResource, c.ns, destinationRule), &v1alpha3.DestinationRule{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.DestinationRule), err
|
||||
}
|
||||
|
||||
// Delete takes name of the destinationRule and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeDestinationRules) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(destinationrulesResource, c.ns, name), &v1alpha3.DestinationRule{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeDestinationRules) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(destinationrulesResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha3.DestinationRuleList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched destinationRule.
|
||||
func (c *FakeDestinationRules) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha3.DestinationRule, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(destinationrulesResource, c.ns, name, pt, data, subresources...), &v1alpha3.DestinationRule{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha3.DestinationRule), err
|
||||
}
|
||||
@@ -28,6 +28,10 @@ type FakeNetworkingV1alpha3 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeNetworkingV1alpha3) DestinationRules(namespace string) v1alpha3.DestinationRuleInterface {
|
||||
return &FakeDestinationRules{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeNetworkingV1alpha3) VirtualServices(namespace string) v1alpha3.VirtualServiceInterface {
|
||||
return &FakeVirtualServices{c, namespace}
|
||||
}
|
||||
|
||||
@@ -18,4 +18,6 @@ limitations under the License.
|
||||
|
||||
package v1alpha3
|
||||
|
||||
type DestinationRuleExpansion interface{}
|
||||
|
||||
type VirtualServiceExpansion interface{}
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
|
||||
type NetworkingV1alpha3Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
DestinationRulesGetter
|
||||
VirtualServicesGetter
|
||||
}
|
||||
|
||||
@@ -35,6 +36,10 @@ type NetworkingV1alpha3Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *NetworkingV1alpha3Client) DestinationRules(namespace string) DestinationRuleInterface {
|
||||
return newDestinationRules(c, namespace)
|
||||
}
|
||||
|
||||
func (c *NetworkingV1alpha3Client) VirtualServices(namespace string) VirtualServiceInterface {
|
||||
return newVirtualServices(c, namespace)
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Flagger().V1alpha3().Canaries().Informer()}, nil
|
||||
|
||||
// Group=networking.istio.io, Version=v1alpha3
|
||||
case istiov1alpha3.SchemeGroupVersion.WithResource("destinationrules"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1alpha3().DestinationRules().Informer()}, nil
|
||||
case istiov1alpha3.SchemeGroupVersion.WithResource("virtualservices"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1alpha3().VirtualServices().Informer()}, nil
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
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 v1alpha3
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
istiov1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3"
|
||||
versioned "github.com/weaveworks/flagger/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/weaveworks/flagger/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha3 "github.com/weaveworks/flagger/pkg/client/listers/istio/v1alpha3"
|
||||
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"
|
||||
)
|
||||
|
||||
// DestinationRuleInformer provides access to a shared informer and lister for
|
||||
// DestinationRules.
|
||||
type DestinationRuleInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1alpha3.DestinationRuleLister
|
||||
}
|
||||
|
||||
type destinationRuleInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewDestinationRuleInformer constructs a new informer for DestinationRule 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 NewDestinationRuleInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredDestinationRuleInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredDestinationRuleInformer constructs a new informer for DestinationRule 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 NewFilteredDestinationRuleInformer(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.NetworkingV1alpha3().DestinationRules(namespace).List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.NetworkingV1alpha3().DestinationRules(namespace).Watch(options)
|
||||
},
|
||||
},
|
||||
&istiov1alpha3.DestinationRule{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *destinationRuleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredDestinationRuleInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *destinationRuleInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&istiov1alpha3.DestinationRule{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *destinationRuleInformer) Lister() v1alpha3.DestinationRuleLister {
|
||||
return v1alpha3.NewDestinationRuleLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@@ -24,6 +24,8 @@ import (
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// DestinationRules returns a DestinationRuleInformer.
|
||||
DestinationRules() DestinationRuleInformer
|
||||
// VirtualServices returns a VirtualServiceInformer.
|
||||
VirtualServices() VirtualServiceInformer
|
||||
}
|
||||
@@ -39,6 +41,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// DestinationRules returns a DestinationRuleInformer.
|
||||
func (v *version) DestinationRules() DestinationRuleInformer {
|
||||
return &destinationRuleInformer{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,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 v1alpha3
|
||||
|
||||
import (
|
||||
v1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// DestinationRuleLister helps list DestinationRules.
|
||||
type DestinationRuleLister interface {
|
||||
// List lists all DestinationRules in the indexer.
|
||||
List(selector labels.Selector) (ret []*v1alpha3.DestinationRule, err error)
|
||||
// DestinationRules returns an object that can list and get DestinationRules.
|
||||
DestinationRules(namespace string) DestinationRuleNamespaceLister
|
||||
DestinationRuleListerExpansion
|
||||
}
|
||||
|
||||
// destinationRuleLister implements the DestinationRuleLister interface.
|
||||
type destinationRuleLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewDestinationRuleLister returns a new DestinationRuleLister.
|
||||
func NewDestinationRuleLister(indexer cache.Indexer) DestinationRuleLister {
|
||||
return &destinationRuleLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all DestinationRules in the indexer.
|
||||
func (s *destinationRuleLister) List(selector labels.Selector) (ret []*v1alpha3.DestinationRule, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1alpha3.DestinationRule))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// DestinationRules returns an object that can list and get DestinationRules.
|
||||
func (s *destinationRuleLister) DestinationRules(namespace string) DestinationRuleNamespaceLister {
|
||||
return destinationRuleNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
// DestinationRuleNamespaceLister helps list and get DestinationRules.
|
||||
type DestinationRuleNamespaceLister interface {
|
||||
// List lists all DestinationRules in the indexer for a given namespace.
|
||||
List(selector labels.Selector) (ret []*v1alpha3.DestinationRule, err error)
|
||||
// Get retrieves the DestinationRule from the indexer for a given namespace and name.
|
||||
Get(name string) (*v1alpha3.DestinationRule, error)
|
||||
DestinationRuleNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// destinationRuleNamespaceLister implements the DestinationRuleNamespaceLister
|
||||
// interface.
|
||||
type destinationRuleNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all DestinationRules in the indexer for a given namespace.
|
||||
func (s destinationRuleNamespaceLister) List(selector labels.Selector) (ret []*v1alpha3.DestinationRule, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1alpha3.DestinationRule))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the DestinationRule from the indexer for a given namespace and name.
|
||||
func (s destinationRuleNamespaceLister) Get(name string) (*v1alpha3.DestinationRule, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1alpha3.Resource("destinationrule"), name)
|
||||
}
|
||||
return obj.(*v1alpha3.DestinationRule), nil
|
||||
}
|
||||
@@ -18,6 +18,14 @@ limitations under the License.
|
||||
|
||||
package v1alpha3
|
||||
|
||||
// DestinationRuleListerExpansion allows custom methods to be added to
|
||||
// DestinationRuleLister.
|
||||
type DestinationRuleListerExpansion interface{}
|
||||
|
||||
// DestinationRuleNamespaceListerExpansion allows custom methods to be added to
|
||||
// DestinationRuleNamespaceLister.
|
||||
type DestinationRuleNamespaceListerExpansion interface{}
|
||||
|
||||
// VirtualServiceListerExpansion allows custom methods to be added to
|
||||
// VirtualServiceLister.
|
||||
type VirtualServiceListerExpansion interface{}
|
||||
|
||||
+78
-29
@@ -23,8 +23,83 @@ type IstioRouter struct {
|
||||
logger *zap.SugaredLogger
|
||||
}
|
||||
|
||||
// Reconcile creates or updates the Istio virtual service
|
||||
// Reconcile creates or updates the Istio virtual service and destination rules
|
||||
func (ir *IstioRouter) Reconcile(canary *flaggerv1.Canary) error {
|
||||
canaryName := fmt.Sprintf("%s-canary", canary.Spec.TargetRef.Name)
|
||||
primaryName := fmt.Sprintf("%s-primary", canary.Spec.TargetRef.Name)
|
||||
|
||||
err := ir.reconcileDestinationRule(canary, canaryName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ir.reconcileDestinationRule(canary, primaryName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ir.reconcileVirtualService(canary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ir *IstioRouter) reconcileDestinationRule(canary *flaggerv1.Canary, name string) error {
|
||||
newSpec := istiov1alpha3.DestinationRuleSpec{
|
||||
Host: name,
|
||||
TrafficPolicy: canary.Spec.Service.TrafficPolicy,
|
||||
}
|
||||
|
||||
destinationRule, err := ir.istioClient.NetworkingV1alpha3().DestinationRules(canary.Namespace).Get(name, metav1.GetOptions{})
|
||||
// insert
|
||||
if errors.IsNotFound(err) {
|
||||
destinationRule = &istiov1alpha3.DestinationRule{
|
||||
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: newSpec,
|
||||
}
|
||||
_, err = ir.istioClient.NetworkingV1alpha3().DestinationRules(canary.Namespace).Create(destinationRule)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DestinationRule %s.%s create error %v", name, canary.Namespace, err)
|
||||
}
|
||||
ir.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
|
||||
Infof("DestinationRule %s.%s created", destinationRule.GetName(), canary.Namespace)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("DestinationRule %s.%s query error %v", name, canary.Namespace, err)
|
||||
}
|
||||
|
||||
// update
|
||||
if destinationRule != nil {
|
||||
if diff := cmp.Diff(newSpec, destinationRule.Spec); diff != "" {
|
||||
clone := destinationRule.DeepCopy()
|
||||
clone.Spec = newSpec
|
||||
_, err = ir.istioClient.NetworkingV1alpha3().DestinationRules(canary.Namespace).Update(clone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DestinationRule %s.%s update error %v", name, canary.Namespace, err)
|
||||
}
|
||||
ir.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
|
||||
Infof("DestinationRule %s.%s updated", destinationRule.GetName(), canary.Namespace)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
|
||||
targetName := canary.Spec.TargetRef.Name
|
||||
primaryName := fmt.Sprintf("%s-primary", targetName)
|
||||
|
||||
@@ -61,18 +136,12 @@ func (ir *IstioRouter) Reconcile(canary *flaggerv1.Canary) error {
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: primaryName,
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(canary.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: 100,
|
||||
},
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: fmt.Sprintf("%s-canary", targetName),
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(canary.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: 0,
|
||||
},
|
||||
@@ -117,9 +186,6 @@ func (ir *IstioRouter) Reconcile(canary *flaggerv1.Canary) error {
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: primaryName,
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(canary.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: 100,
|
||||
},
|
||||
@@ -160,12 +226,10 @@ func (ir *IstioRouter) Reconcile(canary *flaggerv1.Canary) error {
|
||||
|
||||
// update service but keep the original destination weights
|
||||
if virtualService != nil {
|
||||
if diff := cmp.Diff(newSpec, virtualService.Spec, cmpopts.IgnoreTypes(istiov1alpha3.DestinationWeight{})); diff != "" {
|
||||
if diff := cmp.Diff(newSpec, virtualService.Spec, cmpopts.IgnoreFields(istiov1alpha3.DestinationWeight{}, "Weight")); diff != "" {
|
||||
vtClone := virtualService.DeepCopy()
|
||||
vtClone.Spec = newSpec
|
||||
if len(virtualService.Spec.Http) > 0 {
|
||||
vtClone.Spec.Http[0].Route = virtualService.Spec.Http[0].Route
|
||||
}
|
||||
|
||||
_, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Update(vtClone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("VirtualService %s.%s update error %v", targetName, canary.Namespace, err)
|
||||
@@ -254,18 +318,12 @@ func (ir *IstioRouter) SetRoutes(
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: fmt.Sprintf("%s-primary", targetName),
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(canary.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: primaryWeight,
|
||||
},
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: fmt.Sprintf("%s-canary", targetName),
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(canary.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: canaryWeight,
|
||||
},
|
||||
@@ -289,18 +347,12 @@ func (ir *IstioRouter) SetRoutes(
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: fmt.Sprintf("%s-primary", targetName),
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(canary.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: primaryWeight,
|
||||
},
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: fmt.Sprintf("%s-canary", targetName),
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(canary.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: canaryWeight,
|
||||
},
|
||||
@@ -317,9 +369,6 @@ func (ir *IstioRouter) SetRoutes(
|
||||
{
|
||||
Destination: istiov1alpha3.Destination{
|
||||
Host: fmt.Sprintf("%s-primary", targetName),
|
||||
Port: istiov1alpha3.PortSelector{
|
||||
Number: uint32(canary.Spec.Service.Port),
|
||||
},
|
||||
},
|
||||
Weight: primaryWeight,
|
||||
},
|
||||
|
||||
@@ -22,6 +22,16 @@ func TestIstioRouter_Sync(t *testing.T) {
|
||||
}
|
||||
|
||||
// test insert
|
||||
_, err = mocks.meshClient.NetworkingV1alpha3().DestinationRules("default").Get("podinfo-canary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
_, err = mocks.meshClient.NetworkingV1alpha3().DestinationRules("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
|
||||
Reference in New Issue
Block a user