mirror of https://github.com/linkerd/linkerd2.git
smi: remove default functionality in linkerd (#7334)
Now, that SMI functionality is fully being moved into the [linkerd-smi](www.github.com/linkerd/linkerd-smi) extension, we can stop supporting its functionality by default. This means that the `destination` component will stop reacting to the `TrafficSplit` objects. When `linkerd-smi` is installed, It does the conversion of `TrafficSplit` objects to `ServiceProfiles` that destination components can understand, and will react accordingly. Also, Whenever a `ServiceProfile` with traffic splitting is associated with a service, the same information (i.e splits and weights) is also surfaced through the `UI` (in the new `services` tab) and the `viz cmd`. So, We are not really loosing any UI functionality here. Signed-off-by: Tarun Pothulapati <tarunpothulapati@outlook.com>
This commit is contained in:
parent
c384cfd423
commit
4170b49b33
|
|
@ -22,9 +22,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
{{- if .Values.enableEndpointSlices }}
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
{{ include "partials.annotations.created-by" . }}
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: {{.Values.namespace}}
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
|
|
@ -66,7 +66,6 @@ var (
|
|||
"templates/heartbeat-rbac.yaml",
|
||||
"templates/policy-crd.yaml",
|
||||
"templates/serviceprofile-crd.yaml",
|
||||
"templates/trafficsplit-crd.yaml",
|
||||
"templates/proxy-injector-rbac.yaml",
|
||||
"templates/psp.yaml",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1871,7 +1773,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 3290ef57105cdd56ce71577bc09f73cd2e67eb6439f2c76a1c464ce9c65782b5
|
||||
checksum/config: a04430b9c0dc19d9cee251c74b79f9fde7c1be371e4f1899f8116d976a9b73b1
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: l5d
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1870,7 +1772,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: bc1365e89e7f9cff360537ef2b453200e607bf6196d704f84d730f1ad0259beb
|
||||
checksum/config: f87a6023ec5af3bdee3045085ae9d332b340c3f1082d8c36d6f88724e3fcada4
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1870,7 +1772,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 3290ef57105cdd56ce71577bc09f73cd2e67eb6439f2c76a1c464ce9c65782b5
|
||||
checksum/config: a04430b9c0dc19d9cee251c74b79f9fde7c1be371e4f1899f8116d976a9b73b1
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1870,7 +1772,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 3290ef57105cdd56ce71577bc09f73cd2e67eb6439f2c76a1c464ce9c65782b5
|
||||
checksum/config: a04430b9c0dc19d9cee251c74b79f9fde7c1be371e4f1899f8116d976a9b73b1
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1870,7 +1772,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 3290ef57105cdd56ce71577bc09f73cd2e67eb6439f2c76a1c464ce9c65782b5
|
||||
checksum/config: a04430b9c0dc19d9cee251c74b79f9fde7c1be371e4f1899f8116d976a9b73b1
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1861,7 +1763,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 3290ef57105cdd56ce71577bc09f73cd2e67eb6439f2c76a1c464ce9c65782b5
|
||||
checksum/config: a04430b9c0dc19d9cee251c74b79f9fde7c1be371e4f1899f8116d976a9b73b1
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1975,7 +1877,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: f1ebee8ab445c8899db6943a7592ce0e6fd3323171d3207b1872f566115a56ca
|
||||
checksum/config: fd4355b1aba8e27821a6fc4f9b43f57db662b07427eaff21d75b5f91ba33d23d
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1975,7 +1877,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: f1ebee8ab445c8899db6943a7592ce0e6fd3323171d3207b1872f566115a56ca
|
||||
checksum/config: fd4355b1aba8e27821a6fc4f9b43f57db662b07427eaff21d75b5f91ba33d23d
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -957,101 +954,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1801,7 +1703,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 3290ef57105cdd56ce71577bc09f73cd2e67eb6439f2c76a1c464ce9c65782b5
|
||||
checksum/config: a04430b9c0dc19d9cee251c74b79f9fde7c1be371e4f1899f8116d976a9b73b1
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -88,9 +88,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1037,103 +1034,6 @@ spec:
|
|||
shortNames:
|
||||
- sp
|
||||
---
|
||||
# Source: linkerd2/templates/trafficsplit-crd.yaml
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
# Source: linkerd2/templates/proxy-injector-rbac.yaml
|
||||
---
|
||||
###
|
||||
|
|
@ -1863,7 +1763,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 325b45e94ae528bf48ef5e2c16896631879e17c4ce0749488a735f956fc019c1
|
||||
checksum/config: 97f994323d2d6adab8046b822ef898b6df42cb529f1bf95a156d44f46b0eb2a6
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: test-proxy-version
|
||||
|
|
|
|||
|
|
@ -88,9 +88,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1037,103 +1034,6 @@ spec:
|
|||
shortNames:
|
||||
- sp
|
||||
---
|
||||
# Source: linkerd2/templates/trafficsplit-crd.yaml
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
# Source: linkerd2/templates/proxy-injector-rbac.yaml
|
||||
---
|
||||
###
|
||||
|
|
@ -1968,7 +1868,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 6293021b49e905a45aee892e5d1f442e2cc0ad4a4c6a429a6e6678f7e41a794f
|
||||
checksum/config: 79404e88eb110c355862f4a931adbf1d33a3a7d51dfba4e552896d9b345694dc
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: test-proxy-version
|
||||
|
|
|
|||
|
|
@ -88,9 +88,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1037,103 +1034,6 @@ spec:
|
|||
shortNames:
|
||||
- sp
|
||||
---
|
||||
# Source: linkerd2/templates/trafficsplit-crd.yaml
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
# Source: linkerd2/templates/proxy-injector-rbac.yaml
|
||||
---
|
||||
###
|
||||
|
|
@ -1976,7 +1876,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 6293021b49e905a45aee892e5d1f442e2cc0ad4a4c6a429a6e6678f7e41a794f
|
||||
checksum/config: 79404e88eb110c355862f4a931adbf1d33a3a7d51dfba4e552896d9b345694dc
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: test-proxy-version
|
||||
|
|
|
|||
|
|
@ -88,9 +88,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1037,103 +1034,6 @@ spec:
|
|||
shortNames:
|
||||
- sp
|
||||
---
|
||||
# Source: linkerd2/templates/trafficsplit-crd.yaml
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
# Source: linkerd2/templates/proxy-injector-rbac.yaml
|
||||
---
|
||||
###
|
||||
|
|
@ -1968,7 +1868,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 58ce41e5c2826199b8e56e92cc45df6d4c73b7ac8e3d90f10792fe9b913f8da2
|
||||
checksum/config: adf960619bc68a07b1249d57bb0f92e0c24a5bbe5bff6d966b63d24c0f65be6b
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: test-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1833,7 +1735,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 3290ef57105cdd56ce71577bc09f73cd2e67eb6439f2c76a1c464ce9c65782b5
|
||||
checksum/config: a04430b9c0dc19d9cee251c74b79f9fde7c1be371e4f1899f8116d976a9b73b1
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
|
|
@ -1023,101 +1020,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: CliVersion
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1870,7 +1772,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 3b5f3a12c582fc818fa275981006785e6c8f016637331b7656e15c6f41db6f96
|
||||
checksum/config: 794ec047e1dbcff1a459e49ee70a90d0454ed1f8f8df06a7cfeb1aa59e8a4cfb
|
||||
linkerd.io/created-by: CliVersion
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: ProxyVersion
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1026,101 +1023,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1870,7 +1772,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 3290ef57105cdd56ce71577bc09f73cd2e67eb6439f2c76a1c464ce9c65782b5
|
||||
checksum/config: a04430b9c0dc19d9cee251c74b79f9fde7c1be371e4f1899f8116d976a9b73b1
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -68,9 +68,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
|
|
@ -1012,101 +1009,6 @@ spec:
|
|||
- sp
|
||||
---
|
||||
###
|
||||
### TrafficSplit CRD
|
||||
### Copied from github.com/servicemeshinterface/smi-sdk-go/blob/d4e76b1cd7a33ead5f38d1262dd838a31c80f4e5/crds/split.yaml
|
||||
###
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: trafficsplits.split.smi-spec.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
linkerd.io/control-plane-ns: l5d
|
||||
spec:
|
||||
group: split.smi-spec.io
|
||||
scope: Namespaced
|
||||
conversion:
|
||||
strategy: None
|
||||
names:
|
||||
kind: TrafficSplit
|
||||
listKind: TrafficSplitList
|
||||
shortNames:
|
||||
- ts
|
||||
plural: trafficsplits
|
||||
singular: trafficsplit
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
x-kubernetes-int-or-string: true
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
- name: v1alpha2
|
||||
served: true
|
||||
storage: false
|
||||
additionalPrinterColumns:
|
||||
- name: Service
|
||||
type: string
|
||||
description: The apex service of this split.
|
||||
jsonPath: .spec.service
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- backends
|
||||
properties:
|
||||
service:
|
||||
description: The apex service of this split.
|
||||
type: string
|
||||
backends:
|
||||
description: The backend services of this split.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ['service', 'weight']
|
||||
properties:
|
||||
service:
|
||||
description: Name of the Kubernetes service.
|
||||
type: string
|
||||
weight:
|
||||
description: Traffic weight value of this backend.
|
||||
type: number
|
||||
preserveUnknownFields: false
|
||||
---
|
||||
###
|
||||
### Proxy Injector RBAC
|
||||
###
|
||||
kind: ClusterRole
|
||||
|
|
@ -1856,7 +1758,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: bc1365e89e7f9cff360537ef2b453200e607bf6196d704f84d730f1ad0259beb
|
||||
checksum/config: f87a6023ec5af3bdee3045085ae9d332b340c3f1082d8c36d6f88724e3fcada4
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
linkerd.io/identity-mode: default
|
||||
linkerd.io/proxy-version: install-proxy-version
|
||||
|
|
|
|||
|
|
@ -28,11 +28,10 @@ type (
|
|||
server struct {
|
||||
pb.UnimplementedDestinationServer
|
||||
|
||||
endpoints *watcher.EndpointsWatcher
|
||||
opaquePorts *watcher.OpaquePortsWatcher
|
||||
profiles *watcher.ProfileWatcher
|
||||
trafficSplits *watcher.TrafficSplitWatcher
|
||||
nodes coreinformers.NodeInformer
|
||||
endpoints *watcher.EndpointsWatcher
|
||||
opaquePorts *watcher.OpaquePortsWatcher
|
||||
profiles *watcher.ProfileWatcher
|
||||
nodes coreinformers.NodeInformer
|
||||
|
||||
enableH2Upgrade bool
|
||||
controllerNS string
|
||||
|
|
@ -83,14 +82,12 @@ func NewServer(
|
|||
endpoints := watcher.NewEndpointsWatcher(k8sAPI, log, enableEndpointSlices)
|
||||
opaquePorts := watcher.NewOpaquePortsWatcher(k8sAPI, log, defaultOpaquePorts)
|
||||
profiles := watcher.NewProfileWatcher(k8sAPI, log)
|
||||
trafficSplits := watcher.NewTrafficSplitWatcher(k8sAPI, log)
|
||||
|
||||
srv := server{
|
||||
pb.UnimplementedDestinationServer{},
|
||||
endpoints,
|
||||
opaquePorts,
|
||||
profiles,
|
||||
trafficSplits,
|
||||
k8sAPI.Node(),
|
||||
enableH2Upgrade,
|
||||
controllerNS,
|
||||
|
|
@ -268,22 +265,10 @@ func (s *server) GetProfile(dest *pb.GetDestination, stream pb.Destination_GetPr
|
|||
// and pushes them onto the gRPC stream.
|
||||
translator := newProfileTranslator(stream, log, fqn, port, nil)
|
||||
|
||||
// The traffic split adaptor merges profile updates with traffic split
|
||||
// updates and publishes the result to the profile translator.
|
||||
tsAdaptor := newTrafficSplitAdaptor(translator, service, port, s.clusterDomain)
|
||||
|
||||
// Subscribe the adaptor to traffic split updates.
|
||||
err = s.trafficSplits.Subscribe(service, tsAdaptor)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to subscribe to traffic split for %s: %s", path, err)
|
||||
return err
|
||||
}
|
||||
defer s.trafficSplits.Unsubscribe(service, tsAdaptor)
|
||||
|
||||
// The opaque ports adaptor merges profile updates with service opaque
|
||||
// port annotation updates; it then publishes the result to the traffic
|
||||
// split adaptor.
|
||||
opaquePortsAdaptor := newOpaquePortsAdaptor(tsAdaptor)
|
||||
opaquePortsAdaptor := newOpaquePortsAdaptor(translator)
|
||||
|
||||
// Subscribe the adaptor to service updates.
|
||||
err = s.opaquePorts.Subscribe(service, opaquePortsAdaptor)
|
||||
|
|
|
|||
|
|
@ -341,7 +341,6 @@ status:
|
|||
endpoints := watcher.NewEndpointsWatcher(k8sAPI, log, false)
|
||||
opaquePorts := watcher.NewOpaquePortsWatcher(k8sAPI, log, defaultOpaquePorts)
|
||||
profiles := watcher.NewProfileWatcher(k8sAPI, log)
|
||||
trafficSplits := watcher.NewTrafficSplitWatcher(k8sAPI, log)
|
||||
|
||||
// Sync after creating watchers so that the the indexers added get updated
|
||||
// properly
|
||||
|
|
@ -352,7 +351,6 @@ status:
|
|||
endpoints,
|
||||
opaquePorts,
|
||||
profiles,
|
||||
trafficSplits,
|
||||
k8sAPI.Node(),
|
||||
true,
|
||||
"linkerd",
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
package destination
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/linkerd/linkerd2/controller/api/destination/watcher"
|
||||
sp "github.com/linkerd/linkerd2/controller/gen/apis/serviceprofile/v1alpha2"
|
||||
ts "github.com/servicemeshinterface/smi-sdk-go/pkg/apis/split/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
)
|
||||
|
||||
// trafficSplitAdaptor merges traffic splits into service profiles, encoding
|
||||
// them as dst overrides. trafficSplitAdaptor holds an underlying
|
||||
// ProfileUpdateListener and updates that listener with a merged service
|
||||
// service profile which includes the traffic split logic as a dst override
|
||||
// when a traffic split exists. trafficSplitAdaptor itself implements both
|
||||
// ProfileUpdateListener and TrafficSplitUpdateListener and must be passed to
|
||||
// a source of profile updates (such as a ProfileWatcher) and a source of
|
||||
// traffic split updates (such as a TrafficSplitWatcher).
|
||||
type trafficSplitAdaptor struct {
|
||||
listener watcher.ProfileUpdateListener
|
||||
id watcher.ServiceID
|
||||
port watcher.Port
|
||||
profile *sp.ServiceProfile
|
||||
split *ts.TrafficSplit
|
||||
clusterDomain string
|
||||
}
|
||||
|
||||
func newTrafficSplitAdaptor(listener watcher.ProfileUpdateListener, id watcher.ServiceID, port watcher.Port, clusterDomain string) *trafficSplitAdaptor {
|
||||
return &trafficSplitAdaptor{
|
||||
listener: listener,
|
||||
id: id,
|
||||
port: port,
|
||||
clusterDomain: clusterDomain,
|
||||
}
|
||||
}
|
||||
|
||||
func (tsa *trafficSplitAdaptor) Update(profile *sp.ServiceProfile) {
|
||||
tsa.profile = profile
|
||||
tsa.publish()
|
||||
}
|
||||
|
||||
func (tsa *trafficSplitAdaptor) UpdateTrafficSplit(split *ts.TrafficSplit) {
|
||||
if tsa.split == nil && split == nil {
|
||||
return
|
||||
}
|
||||
tsa.split = split
|
||||
tsa.publish()
|
||||
}
|
||||
|
||||
func (tsa *trafficSplitAdaptor) publish() {
|
||||
merged := sp.ServiceProfile{}
|
||||
if tsa.profile != nil {
|
||||
merged = *tsa.profile
|
||||
}
|
||||
|
||||
// Update only if `dstOverrides` is empty, to give preference
|
||||
// to serviceprofiles over trafficsplits
|
||||
if tsa.split != nil && len(merged.Spec.DstOverrides) == 0 {
|
||||
overrides := []*sp.WeightedDst{}
|
||||
for _, backend := range tsa.split.Spec.Backends {
|
||||
dst := &sp.WeightedDst{
|
||||
// The proxy expects authorities to be absolute and have the
|
||||
// host part end with a trailing dot.
|
||||
Authority: fmt.Sprintf("%s.%s.svc.%s.:%d", backend.Service, tsa.id.Namespace, tsa.clusterDomain, tsa.port),
|
||||
Weight: *backend.Weight,
|
||||
}
|
||||
overrides = append(overrides, dst)
|
||||
}
|
||||
merged.Spec.DstOverrides = overrides
|
||||
}
|
||||
|
||||
// If there are no destination overrides set, always return a destination override
|
||||
// so that it's known the host is a service.
|
||||
if len(merged.Spec.DstOverrides) == 0 {
|
||||
dst := &sp.WeightedDst{
|
||||
Authority: fmt.Sprintf("%s.%s.svc.%s.:%d", tsa.id.Name, tsa.id.Namespace, tsa.clusterDomain, tsa.port),
|
||||
Weight: resource.MustParse("1"),
|
||||
}
|
||||
merged.Spec.DstOverrides = []*sp.WeightedDst{dst}
|
||||
}
|
||||
|
||||
tsa.listener.Update(&merged)
|
||||
}
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
package destination
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/linkerd/linkerd2/controller/api/destination/watcher"
|
||||
sp "github.com/linkerd/linkerd2/controller/gen/apis/serviceprofile/v1alpha2"
|
||||
ts "github.com/servicemeshinterface/smi-sdk-go/pkg/apis/split/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
)
|
||||
|
||||
func TestTrafficSplitAdaptor(t *testing.T) {
|
||||
|
||||
profile := &sp.ServiceProfile{
|
||||
Spec: sp.ServiceProfileSpec{
|
||||
Routes: []*sp.RouteSpec{
|
||||
{
|
||||
Name: "route",
|
||||
},
|
||||
},
|
||||
DstOverrides: []*sp.WeightedDst{
|
||||
{
|
||||
Authority: "foo.ns.svc.cluster.local.:80",
|
||||
Weight: resource.MustParse("1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
weight := resource.MustParse("1000m")
|
||||
split := &ts.TrafficSplit{
|
||||
Spec: ts.TrafficSplitSpec{
|
||||
Backends: []ts.TrafficSplitBackend{
|
||||
{
|
||||
Service: "bar",
|
||||
Weight: &weight,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("Profile update", func(t *testing.T) {
|
||||
listener := watcher.NewBufferingProfileListener()
|
||||
adaptor := newTrafficSplitAdaptor(listener, watcher.ServiceID{Name: "foo", Namespace: "ns"}, watcher.Port(80), "cluster.local")
|
||||
|
||||
adaptor.Update(profile)
|
||||
|
||||
if len(listener.Profiles) != 1 {
|
||||
t.Fatalf("Expected one profile updated, got %d", len(listener.Profiles))
|
||||
}
|
||||
testCompare(t, profile.Spec, listener.Profiles[0].Spec)
|
||||
})
|
||||
|
||||
t.Run("Traffic split without profile", func(t *testing.T) {
|
||||
listener := watcher.NewBufferingProfileListener()
|
||||
adaptor := newTrafficSplitAdaptor(listener, watcher.ServiceID{Name: "foo", Namespace: "ns"}, watcher.Port(80), "cluster.local")
|
||||
|
||||
adaptor.UpdateTrafficSplit(split)
|
||||
|
||||
if len(listener.Profiles) != 1 {
|
||||
t.Fatalf("Expected one profile updated, got %d", len(listener.Profiles))
|
||||
}
|
||||
|
||||
expected := &sp.ServiceProfile{
|
||||
Spec: sp.ServiceProfileSpec{
|
||||
DstOverrides: []*sp.WeightedDst{
|
||||
{
|
||||
Authority: "bar.ns.svc.cluster.local.:80",
|
||||
Weight: resource.MustParse("1000m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testCompare(t, expected.Spec, listener.Profiles[0].Spec)
|
||||
})
|
||||
|
||||
t.Run("Profile merged with traffic split when `dstOverrides` is empty", func(t *testing.T) {
|
||||
listener := watcher.NewBufferingProfileListener()
|
||||
adaptor := newTrafficSplitAdaptor(listener, watcher.ServiceID{Name: "foo", Namespace: "ns"}, watcher.Port(80), "cluster.local")
|
||||
|
||||
adaptor.Update(&sp.ServiceProfile{
|
||||
Spec: sp.ServiceProfileSpec{
|
||||
Routes: []*sp.RouteSpec{
|
||||
{
|
||||
Name: "route",
|
||||
},
|
||||
},
|
||||
DstOverrides: []*sp.WeightedDst{},
|
||||
},
|
||||
})
|
||||
adaptor.UpdateTrafficSplit(split)
|
||||
|
||||
if len(listener.Profiles) != 2 {
|
||||
t.Fatalf("Expected two profile updated, got %d", len(listener.Profiles))
|
||||
}
|
||||
|
||||
expected := &sp.ServiceProfile{
|
||||
Spec: sp.ServiceProfileSpec{
|
||||
Routes: []*sp.RouteSpec{
|
||||
{
|
||||
Name: "route",
|
||||
},
|
||||
},
|
||||
DstOverrides: []*sp.WeightedDst{
|
||||
{
|
||||
Authority: "bar.ns.svc.cluster.local.:80",
|
||||
Weight: resource.MustParse("1000m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testCompare(t, expected.Spec, listener.Profiles[1].Spec)
|
||||
})
|
||||
|
||||
t.Run("Profile taking priority over traffic split when `dstOverrides` is not empty", func(t *testing.T) {
|
||||
listener := watcher.NewBufferingProfileListener()
|
||||
adaptor := newTrafficSplitAdaptor(listener, watcher.ServiceID{Name: "foo", Namespace: "ns"}, watcher.Port(80), "cluster.local")
|
||||
|
||||
adaptor.Update(profile)
|
||||
adaptor.UpdateTrafficSplit(split)
|
||||
|
||||
if len(listener.Profiles) != 2 {
|
||||
t.Fatalf("Expected two profile updated, got %d", len(listener.Profiles))
|
||||
}
|
||||
|
||||
expected := &sp.ServiceProfile{
|
||||
Spec: sp.ServiceProfileSpec{
|
||||
Routes: []*sp.RouteSpec{
|
||||
{
|
||||
Name: "route",
|
||||
},
|
||||
},
|
||||
DstOverrides: []*sp.WeightedDst{
|
||||
{
|
||||
Authority: "foo.ns.svc.cluster.local.:80",
|
||||
Weight: resource.MustParse("1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testCompare(t, expected.Spec, listener.Profiles[1].Spec)
|
||||
})
|
||||
}
|
||||
|
||||
func testCompare(t *testing.T, expected interface{}, actual interface{}) {
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
expectedBytes, _ := json.Marshal(expected)
|
||||
actualBytes, _ := json.Marshal(actual)
|
||||
t.Fatalf("Expected %s but got %s", string(expectedBytes), string(actualBytes))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
package watcher
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/linkerd/linkerd2/controller/k8s"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
ts "github.com/servicemeshinterface/smi-sdk-go/pkg/apis/split/v1alpha1"
|
||||
tslisters "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/listers/split/v1alpha1"
|
||||
logging "github.com/sirupsen/logrus"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type (
|
||||
// TrafficSplitWatcher watches all TrafficSplits in the Kubernetes cluster.
|
||||
// Listeners can subscribe to a particular apex service and
|
||||
// TrafficSplitWatcher will publish all TrafficSplits for that apex service.
|
||||
TrafficSplitWatcher struct {
|
||||
tsLister tslisters.TrafficSplitLister
|
||||
publishers map[ServiceID]*trafficSplitPublisher
|
||||
|
||||
log *logging.Entry
|
||||
sync.RWMutex // This mutex protects modification of the map itself.
|
||||
}
|
||||
|
||||
trafficSplitPublisher struct {
|
||||
split *ts.TrafficSplit
|
||||
listeners []TrafficSplitUpdateListener
|
||||
|
||||
log *logging.Entry
|
||||
splitMetrics metrics
|
||||
// All access to the trafficSplitPublisher is explicitly synchronized by this mutex.
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// TrafficSplitUpdateListener is the interface that subscribers must implement.
|
||||
TrafficSplitUpdateListener interface {
|
||||
UpdateTrafficSplit(split *ts.TrafficSplit)
|
||||
}
|
||||
)
|
||||
|
||||
var splitVecs = newMetricsVecs("trafficsplit", []string{"namespace", "service"})
|
||||
|
||||
// NewTrafficSplitWatcher creates a TrafficSplitWatcher and begins watching the k8sAPI for
|
||||
// TrafficSplit changes.
|
||||
func NewTrafficSplitWatcher(k8sAPI *k8s.API, log *logging.Entry) *TrafficSplitWatcher {
|
||||
watcher := &TrafficSplitWatcher{
|
||||
tsLister: k8sAPI.TS().Lister(),
|
||||
publishers: make(map[ServiceID]*trafficSplitPublisher),
|
||||
log: log.WithField("component", "traffic-split-watcher"),
|
||||
}
|
||||
|
||||
k8sAPI.TS().Informer().AddEventHandler(
|
||||
cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: watcher.addTrafficSplit,
|
||||
UpdateFunc: watcher.updateTrafficSplit,
|
||||
DeleteFunc: watcher.deleteTrafficSplit,
|
||||
},
|
||||
)
|
||||
|
||||
return watcher
|
||||
}
|
||||
|
||||
///
|
||||
/// TrafficSplitWatcher
|
||||
///
|
||||
|
||||
// Subscribe to a service.
|
||||
// Each time a traffic split is updated with the given apex service, the
|
||||
// listener will be updated.
|
||||
func (tsw *TrafficSplitWatcher) Subscribe(id ServiceID, listener TrafficSplitUpdateListener) error {
|
||||
tsw.log.Debugf("Establishing watch on service %s", id)
|
||||
|
||||
publisher := tsw.getOrNewTrafficSplitPublisher(id, nil)
|
||||
|
||||
publisher.subscribe(listener)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unsubscribe removes a listener from the subscribers list for this service.
|
||||
func (tsw *TrafficSplitWatcher) Unsubscribe(id ServiceID, listener TrafficSplitUpdateListener) error {
|
||||
tsw.log.Debugf("Stopping watch on profile %s", id)
|
||||
|
||||
publisher, ok := tsw.getTrafficSplitPublisher(id)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot unsubscribe from unknown service [%s] ", id)
|
||||
}
|
||||
publisher.unsubscribe(listener)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tsw *TrafficSplitWatcher) addTrafficSplit(obj interface{}) {
|
||||
split := obj.(*ts.TrafficSplit)
|
||||
id := ServiceID{
|
||||
Name: split.Spec.Service,
|
||||
Namespace: split.Namespace,
|
||||
}
|
||||
|
||||
publisher := tsw.getOrNewTrafficSplitPublisher(id, split)
|
||||
|
||||
publisher.update(split)
|
||||
}
|
||||
|
||||
func (tsw *TrafficSplitWatcher) updateTrafficSplit(old interface{}, new interface{}) {
|
||||
tsw.addTrafficSplit(new)
|
||||
}
|
||||
|
||||
func (tsw *TrafficSplitWatcher) deleteTrafficSplit(obj interface{}) {
|
||||
split, ok := obj.(*ts.TrafficSplit)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
tsw.log.Errorf("couldn't get object from DeletedFinalStateUnknown %#v", obj)
|
||||
return
|
||||
}
|
||||
split, ok = tombstone.Obj.(*ts.TrafficSplit)
|
||||
if !ok {
|
||||
tsw.log.Errorf("DeletedFinalStateUnknown contained object that is not a TrafficSplit %#v", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
id := ServiceID{
|
||||
Name: split.Spec.Service,
|
||||
Namespace: split.Namespace,
|
||||
}
|
||||
|
||||
publisher, ok := tsw.getTrafficSplitPublisher(id)
|
||||
if ok {
|
||||
publisher.update(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (tsw *TrafficSplitWatcher) getOrNewTrafficSplitPublisher(id ServiceID, split *ts.TrafficSplit) *trafficSplitPublisher {
|
||||
tsw.Lock()
|
||||
defer tsw.Unlock()
|
||||
|
||||
publisher, ok := tsw.publishers[id]
|
||||
if !ok {
|
||||
if split == nil {
|
||||
var err error
|
||||
split, err = tsw.tsLister.TrafficSplits(id.Namespace).Get(id.Name)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
tsw.log.Errorf("error getting TrafficSplit: %s", err)
|
||||
}
|
||||
if err != nil {
|
||||
split = nil
|
||||
}
|
||||
}
|
||||
|
||||
publisher = &trafficSplitPublisher{
|
||||
split: split,
|
||||
listeners: make([]TrafficSplitUpdateListener, 0),
|
||||
log: tsw.log.WithFields(logging.Fields{
|
||||
"component": "traffic-split-publisher",
|
||||
"ns": id.Namespace,
|
||||
"service": id.Name,
|
||||
}),
|
||||
splitMetrics: splitVecs.newMetrics(prometheus.Labels{
|
||||
"namespace": id.Namespace,
|
||||
"service": id.Name,
|
||||
}),
|
||||
}
|
||||
tsw.publishers[id] = publisher
|
||||
}
|
||||
|
||||
return publisher
|
||||
}
|
||||
|
||||
func (tsw *TrafficSplitWatcher) getTrafficSplitPublisher(id ServiceID) (publisher *trafficSplitPublisher, ok bool) {
|
||||
tsw.RLock()
|
||||
defer tsw.RUnlock()
|
||||
publisher, ok = tsw.publishers[id]
|
||||
return
|
||||
}
|
||||
|
||||
///
|
||||
/// trafficSplitPublisher
|
||||
///
|
||||
|
||||
func (tsp *trafficSplitPublisher) subscribe(listener TrafficSplitUpdateListener) {
|
||||
tsp.Lock()
|
||||
defer tsp.Unlock()
|
||||
|
||||
tsp.listeners = append(tsp.listeners, listener)
|
||||
listener.UpdateTrafficSplit(tsp.split)
|
||||
|
||||
tsp.splitMetrics.setSubscribers(len(tsp.listeners))
|
||||
}
|
||||
|
||||
func (tsp *trafficSplitPublisher) unsubscribe(listener TrafficSplitUpdateListener) {
|
||||
tsp.Lock()
|
||||
defer tsp.Unlock()
|
||||
|
||||
for i, item := range tsp.listeners {
|
||||
if item == listener {
|
||||
// delete the item from the slice
|
||||
n := len(tsp.listeners)
|
||||
tsp.listeners[i] = tsp.listeners[n-1]
|
||||
tsp.listeners[n-1] = nil
|
||||
tsp.listeners = tsp.listeners[:n-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
tsp.splitMetrics.setSubscribers(len(tsp.listeners))
|
||||
}
|
||||
|
||||
func (tsp *trafficSplitPublisher) update(split *ts.TrafficSplit) {
|
||||
tsp.Lock()
|
||||
defer tsp.Unlock()
|
||||
tsp.log.Debug("Updating TrafficSplit")
|
||||
|
||||
tsp.split = split
|
||||
for _, listener := range tsp.listeners {
|
||||
listener.UpdateTrafficSplit(split)
|
||||
}
|
||||
|
||||
tsp.splitMetrics.incUpdates()
|
||||
}
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
package watcher
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"github.com/linkerd/linkerd2/controller/k8s"
|
||||
ts "github.com/servicemeshinterface/smi-sdk-go/pkg/apis/split/v1alpha1"
|
||||
logging "github.com/sirupsen/logrus"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type bufferingTrafficSplitListener struct {
|
||||
splits []*ts.TrafficSplit
|
||||
}
|
||||
|
||||
func newBufferingTrafficSplitListener() *bufferingTrafficSplitListener {
|
||||
return &bufferingTrafficSplitListener{
|
||||
splits: []*ts.TrafficSplit{},
|
||||
}
|
||||
}
|
||||
|
||||
func (btsl *bufferingTrafficSplitListener) UpdateTrafficSplit(split *ts.TrafficSplit) {
|
||||
btsl.splits = append(btsl.splits, split)
|
||||
}
|
||||
|
||||
type deletingTrafficSplitListener struct {
|
||||
NumDeletes int
|
||||
}
|
||||
|
||||
func newDeletingTrafficSplitListener() *deletingTrafficSplitListener {
|
||||
return &deletingTrafficSplitListener{
|
||||
NumDeletes: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (dpl *deletingTrafficSplitListener) UpdateTrafficSplit(ts *ts.TrafficSplit) {
|
||||
if ts == nil {
|
||||
dpl.NumDeletes = dpl.NumDeletes + 1
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
testTrafficSplitResource = `
|
||||
apiVersion: split.smi-spec.io/v1alpha1
|
||||
kind: TrafficSplit
|
||||
metadata:
|
||||
name: split
|
||||
namespace: ns
|
||||
spec:
|
||||
service: foo
|
||||
backends:
|
||||
- service: foo-v1
|
||||
weight: 500m
|
||||
- service: foo-v2
|
||||
weight: 500m`
|
||||
|
||||
weight = resource.MustParse("500m")
|
||||
testTrafficSplit = ts.TrafficSplit{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "split",
|
||||
Namespace: "ns",
|
||||
},
|
||||
Spec: ts.TrafficSplitSpec{
|
||||
Service: "foo",
|
||||
Backends: []ts.TrafficSplitBackend{
|
||||
{
|
||||
Service: "foo-v1",
|
||||
Weight: &weight,
|
||||
},
|
||||
{
|
||||
Service: "foo-v2",
|
||||
Weight: &weight,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func TestTrafficSplitWatcher(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
k8sConfigs []string
|
||||
service ServiceID
|
||||
expectedSplits []*ts.TrafficSplitSpec
|
||||
}{
|
||||
{
|
||||
name: "traffic split",
|
||||
k8sConfigs: []string{testTrafficSplitResource},
|
||||
service: ServiceID{
|
||||
Name: "foo",
|
||||
Namespace: "ns",
|
||||
},
|
||||
expectedSplits: []*ts.TrafficSplitSpec{&testTrafficSplit.Spec},
|
||||
},
|
||||
{
|
||||
name: "no traffic split",
|
||||
k8sConfigs: []string{},
|
||||
service: ServiceID{
|
||||
Name: "foo",
|
||||
Namespace: "ns",
|
||||
},
|
||||
expectedSplits: []*ts.TrafficSplitSpec{
|
||||
nil,
|
||||
},
|
||||
},
|
||||
} {
|
||||
tt := tt // pin
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
k8sAPI, err := k8s.NewFakeAPI(tt.k8sConfigs...)
|
||||
if err != nil {
|
||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||
}
|
||||
|
||||
watcher := NewTrafficSplitWatcher(k8sAPI, logging.WithField("test", t.Name()))
|
||||
|
||||
k8sAPI.Sync(nil)
|
||||
|
||||
listener := newBufferingTrafficSplitListener()
|
||||
|
||||
watcher.Subscribe(tt.service, listener)
|
||||
|
||||
actual := make([]*ts.TrafficSplitSpec, 0)
|
||||
|
||||
for _, split := range listener.splits {
|
||||
if split == nil {
|
||||
actual = append(actual, nil)
|
||||
} else {
|
||||
actual = append(actual, &split.Spec)
|
||||
}
|
||||
}
|
||||
|
||||
testCompare(t, tt.expectedSplits, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrafficSplitWatcherDelete(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
k8sConfigs []string
|
||||
service ServiceID
|
||||
objectToDelete interface{}
|
||||
}{
|
||||
{
|
||||
name: "can delete a traffic splits",
|
||||
k8sConfigs: []string{testTrafficSplitResource},
|
||||
service: ServiceID{
|
||||
Name: "foo",
|
||||
Namespace: "ns",
|
||||
},
|
||||
objectToDelete: &testTrafficSplit,
|
||||
},
|
||||
{
|
||||
name: "can delete a traffic splits wrapped in a DeletedFinalStateUnknown",
|
||||
k8sConfigs: []string{testTrafficSplitResource},
|
||||
service: ServiceID{
|
||||
Name: "foo",
|
||||
Namespace: "ns",
|
||||
},
|
||||
objectToDelete: cache.DeletedFinalStateUnknown{Obj: &testTrafficSplit},
|
||||
},
|
||||
} {
|
||||
tt := tt // pin
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
k8sAPI, err := k8s.NewFakeAPI(tt.k8sConfigs...)
|
||||
if err != nil {
|
||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||
}
|
||||
|
||||
watcher := NewTrafficSplitWatcher(k8sAPI, logging.WithField("test", t.Name()))
|
||||
|
||||
k8sAPI.Sync(nil)
|
||||
|
||||
listener := newDeletingTrafficSplitListener()
|
||||
|
||||
watcher.Subscribe(tt.service, listener)
|
||||
|
||||
watcher.deleteTrafficSplit(tt.objectToDelete)
|
||||
if listener.NumDeletes != 1 {
|
||||
t.Fatalf("Expected to get 1 deletes but got %v", listener.NumDeletes)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -94,14 +94,14 @@ func Main(args []string) {
|
|||
ctx,
|
||||
*kubeConfigPath,
|
||||
true,
|
||||
k8s.Endpoint, k8s.ES, k8s.Pod, k8s.RS, k8s.Svc, k8s.SP, k8s.TS, k8s.Job, k8s.NS, k8s.Node, k8s.Srv,
|
||||
k8s.Endpoint, k8s.ES, k8s.Pod, k8s.RS, k8s.Svc, k8s.SP, k8s.Job, k8s.NS, k8s.Node, k8s.Srv,
|
||||
)
|
||||
} else {
|
||||
k8sAPI, err = k8s.InitializeAPI(
|
||||
ctx,
|
||||
*kubeConfigPath,
|
||||
true,
|
||||
k8s.Endpoint, k8s.Pod, k8s.RS, k8s.Svc, k8s.SP, k8s.TS, k8s.Job, k8s.NS, k8s.Node, k8s.Srv,
|
||||
k8s.Endpoint, k8s.Pod, k8s.RS, k8s.Svc, k8s.SP, k8s.Job, k8s.NS, k8s.Node, k8s.Srv,
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@ import (
|
|||
spinformers "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/serviceprofile/v1alpha2"
|
||||
"github.com/linkerd/linkerd2/pkg/k8s"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
tsclient "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned"
|
||||
ts "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/informers/externalversions"
|
||||
tsinformers "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/informers/externalversions/split/v1alpha1"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
|
@ -62,7 +59,6 @@ const (
|
|||
SP
|
||||
SS
|
||||
Svc
|
||||
TS
|
||||
Node
|
||||
Secret
|
||||
ES // EndpointSlice resource
|
||||
|
|
@ -90,7 +86,6 @@ type API struct {
|
|||
sp spinformers.ServiceProfileInformer
|
||||
ss appv1informers.StatefulSetInformer
|
||||
svc coreinformers.ServiceInformer
|
||||
ts tsinformers.TrafficSplitInformer
|
||||
node coreinformers.NodeInformer
|
||||
secret coreinformers.SecretInformer
|
||||
srv srvinformers.ServerInformer
|
||||
|
|
@ -98,7 +93,6 @@ type API struct {
|
|||
syncChecks []cache.InformerSynced
|
||||
sharedInformers informers.SharedInformerFactory
|
||||
l5dCrdSharedInformers l5dcrdinformer.SharedInformerFactory
|
||||
tsSharedInformers ts.SharedInformerFactory
|
||||
|
||||
gauges []prometheus.GaugeFunc
|
||||
}
|
||||
|
|
@ -168,20 +162,7 @@ func initAPI(ctx context.Context, k8sClient *k8s.KubernetesAPI, dynamicClient dy
|
|||
break
|
||||
}
|
||||
|
||||
// TrafficSplits
|
||||
var tsClient *tsclient.Clientset
|
||||
for _, res := range resources {
|
||||
if res == TS {
|
||||
tsClient, err = NewTsClientSet(kubeConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
api := NewAPI(k8sClient, dynamicClient, l5dCrdClient, tsClient, resources...)
|
||||
api := NewAPI(k8sClient, dynamicClient, l5dCrdClient, resources...)
|
||||
for _, gauge := range api.gauges {
|
||||
prometheus.Register(gauge)
|
||||
}
|
||||
|
|
@ -193,7 +174,6 @@ func NewAPI(
|
|||
k8sClient kubernetes.Interface,
|
||||
dynamicClient dynamic.Interface,
|
||||
l5dCrdClient l5dcrdclient.Interface,
|
||||
tsClient tsclient.Interface,
|
||||
resources ...APIResource,
|
||||
) *API {
|
||||
sharedInformers := informers.NewSharedInformerFactory(k8sClient, 10*time.Minute)
|
||||
|
|
@ -203,18 +183,12 @@ func NewAPI(
|
|||
l5dCrdSharedInformers = l5dcrdinformer.NewSharedInformerFactory(l5dCrdClient, 10*time.Minute)
|
||||
}
|
||||
|
||||
var tsSharedInformers ts.SharedInformerFactory
|
||||
if tsClient != nil {
|
||||
tsSharedInformers = ts.NewSharedInformerFactory(tsClient, 10*time.Minute)
|
||||
}
|
||||
|
||||
api := &API{
|
||||
Client: k8sClient,
|
||||
DynamicClient: dynamicClient,
|
||||
syncChecks: make([]cache.InformerSynced, 0),
|
||||
sharedInformers: sharedInformers,
|
||||
l5dCrdSharedInformers: l5dCrdSharedInformers,
|
||||
tsSharedInformers: tsSharedInformers,
|
||||
}
|
||||
|
||||
for _, resource := range resources {
|
||||
|
|
@ -289,13 +263,6 @@ func NewAPI(
|
|||
api.svc = sharedInformers.Core().V1().Services()
|
||||
api.syncChecks = append(api.syncChecks, api.svc.Informer().HasSynced)
|
||||
api.addInformerSizeGauge("service", api.svc.Informer())
|
||||
case TS:
|
||||
if tsSharedInformers == nil {
|
||||
panic("TS shared informer not configured")
|
||||
}
|
||||
api.ts = tsSharedInformers.Split().V1alpha1().TrafficSplits()
|
||||
api.syncChecks = append(api.syncChecks, api.ts.Informer().HasSynced)
|
||||
api.addInformerSizeGauge("traffic_split", api.ts.Informer())
|
||||
case Node:
|
||||
api.node = sharedInformers.Core().V1().Nodes()
|
||||
api.syncChecks = append(api.syncChecks, api.node.Informer().HasSynced)
|
||||
|
|
@ -317,10 +284,6 @@ func (api *API) Sync(stopCh <-chan struct{}) {
|
|||
api.l5dCrdSharedInformers.Start(stopCh)
|
||||
}
|
||||
|
||||
if api.tsSharedInformers != nil {
|
||||
api.tsSharedInformers.Start(stopCh)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer cancel()
|
||||
|
||||
|
|
@ -458,14 +421,6 @@ func (api *API) SPAvailable() bool {
|
|||
return api.sp != nil
|
||||
}
|
||||
|
||||
// TS provides access to a shared informer and lister for TrafficSplits.
|
||||
func (api *API) TS() tsinformers.TrafficSplitInformer {
|
||||
if api.ts == nil {
|
||||
panic("TS informer not configured")
|
||||
}
|
||||
return api.ts
|
||||
}
|
||||
|
||||
// Node provides access to a shared informer and lister for Nodes.
|
||||
func (api *API) Node() coreinformers.NodeInformer {
|
||||
if api.node == nil {
|
||||
|
|
@ -1056,25 +1011,10 @@ func (api *API) GetServicesFor(obj runtime.Object, includeFailed bool) ([]*corev
|
|||
}
|
||||
services := make([]*corev1.Service, 0)
|
||||
for _, svc := range allServices {
|
||||
leaves, err := api.getLeafServices(svc)
|
||||
svcPods, err := api.GetPodsFor(svc, includeFailed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
svcPods := []*corev1.Pod{}
|
||||
if len(leaves) > 0 {
|
||||
for _, leaf := range leaves {
|
||||
pods, err := api.GetPodsFor(leaf, includeFailed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
svcPods = append(svcPods, pods...)
|
||||
}
|
||||
} else {
|
||||
svcPods, err = api.GetPodsFor(svc, includeFailed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if hasOverlap(pods, svcPods) {
|
||||
services = append(services, svc)
|
||||
|
|
@ -1083,29 +1023,6 @@ func (api *API) GetServicesFor(obj runtime.Object, includeFailed bool) ([]*corev
|
|||
return services, nil
|
||||
}
|
||||
|
||||
func (api *API) getLeafServices(apex *corev1.Service) ([]*corev1.Service, error) {
|
||||
splits, err := api.TS().Lister().TrafficSplits(apex.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
leaves := []*corev1.Service{}
|
||||
for _, split := range splits {
|
||||
if split.Spec.Service == apex.Name {
|
||||
for _, backend := range split.Spec.Backends {
|
||||
if backend.Weight.Sign() == 1 {
|
||||
svc, err := api.Svc().Lister().Services(apex.Namespace).Get(backend.Service)
|
||||
if err != nil {
|
||||
log.Errorf("TrafficSplit %s/%s references non-existent service %s", apex.Namespace, split.Name, backend.Service)
|
||||
continue
|
||||
}
|
||||
leaves = append(leaves, svc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return leaves, nil
|
||||
}
|
||||
|
||||
// GetServiceProfileFor returns the service profile for a given service. We
|
||||
// first look for a matching service profile in the client's namespace. If not
|
||||
// found, we then look in the service's namespace. If no service profile is
|
||||
|
|
|
|||
|
|
@ -1274,67 +1274,6 @@ spec:
|
|||
},
|
||||
k8sResMisc: []string{},
|
||||
},
|
||||
// If a service is the apex of a traffic split, GetPodsFor should
|
||||
// return the pods of the backends.
|
||||
{
|
||||
err: nil,
|
||||
k8sResInput: `
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: leaf-1-pod
|
||||
namespace: emojivoto
|
||||
labels:
|
||||
app: leaf-1
|
||||
status:
|
||||
phase: Running`,
|
||||
k8sResResults: []string{`
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: apex
|
||||
namespace: emojivoto
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: apex`,
|
||||
`
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: leaf-1
|
||||
namespace: emojivoto
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: leaf-1`,
|
||||
},
|
||||
k8sResMisc: []string{`
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: leaf-2
|
||||
namespace: emojivoto
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: leaf-2`,
|
||||
`
|
||||
apiVersion: split.smi-spec.io/v1alpha1
|
||||
kind: TrafficSplit
|
||||
metadata:
|
||||
name: banana-split
|
||||
namespace: emojivoto
|
||||
spec:
|
||||
service: apex
|
||||
backends:
|
||||
- service: leaf-1
|
||||
weight: 500m
|
||||
- service: leaf-2
|
||||
weight: 500m`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, exp := range expectations {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package k8s
|
|||
import (
|
||||
l5dcrdclient "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned"
|
||||
"github.com/linkerd/linkerd2/pkg/prometheus"
|
||||
tsclient "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
// Load all the auth plugins for the cloud providers.
|
||||
|
|
@ -21,9 +20,3 @@ func wrapTransport(config *rest.Config, telemetryName string) *rest.Config {
|
|||
func NewL5DCRDClient(kubeConfig *rest.Config) (*l5dcrdclient.Clientset, error) {
|
||||
return l5dcrdclient.NewForConfig(wrapTransport(kubeConfig, "l5dCrd"))
|
||||
}
|
||||
|
||||
// NewTsClientSet returns a Kubernetes TrafficSplit client for the given
|
||||
// configuration.
|
||||
func NewTsClientSet(kubeConfig *rest.Config) (*tsclient.Clientset, error) {
|
||||
return tsclient.NewForConfig(wrapTransport(kubeConfig, "ts"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
// NewFakeAPI provides a mock Kubernetes API for testing.
|
||||
func NewFakeAPI(configs ...string) (*API, error) {
|
||||
clientSet, _, _, spClientSet, tsClientSet, err := k8s.NewFakeClientSets(configs...)
|
||||
clientSet, _, _, spClientSet, err := k8s.NewFakeClientSets(configs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ func NewFakeAPI(configs ...string) (*API, error) {
|
|||
clientSet,
|
||||
nil,
|
||||
spClientSet,
|
||||
tsClientSet,
|
||||
CJ,
|
||||
CM,
|
||||
Deploy,
|
||||
|
|
@ -30,7 +29,6 @@ func NewFakeAPI(configs ...string) (*API, error) {
|
|||
SP,
|
||||
SS,
|
||||
Svc,
|
||||
TS,
|
||||
Node,
|
||||
ES,
|
||||
Srv,
|
||||
|
|
|
|||
3
go.mod
3
go.mod
|
|
@ -29,7 +29,7 @@ require (
|
|||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/prometheus/common v0.32.1
|
||||
github.com/sergi/go-diff v1.2.0
|
||||
github.com/servicemeshinterface/smi-sdk-go v0.5.0
|
||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
|
||||
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/cobra v1.2.1
|
||||
|
|
@ -131,7 +131,6 @@ require (
|
|||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
|
|
|
|||
46
go.sum
46
go.sum
|
|
@ -49,28 +49,21 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg6
|
|||
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
|
||||
github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM=
|
||||
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
|
||||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
|
|
@ -114,10 +107,8 @@ github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:m
|
|||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
|
||||
|
|
@ -365,7 +356,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
|||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
|
|
@ -409,21 +399,17 @@ github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg
|
|||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
|
||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
|
||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
||||
github.com/go-openapi/spec v0.19.5 h1:Xm0Ao53uqnk9QE/LlYV5DEU09UAgpliA85QoT9LzqPw=
|
||||
github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
|
||||
|
|
@ -468,7 +454,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
|||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
|
@ -533,14 +518,10 @@ github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
|||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
||||
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
|
|
@ -601,7 +582,6 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
|
|||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
|
|
@ -614,7 +594,6 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E
|
|||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
|
|
@ -661,7 +640,6 @@ github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z
|
|||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
|
|
@ -865,8 +843,6 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW
|
|||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/servicemeshinterface/smi-sdk-go v0.5.0 h1:9cZdhvGbGDlmnp9qqmcQL+RL6KZ3IzHfDLoA5Axg8n0=
|
||||
github.com/servicemeshinterface/smi-sdk-go v0.5.0/go.mod h1:nm1Slf3pfaZPP3g2tE/K5wDmQ1uWVSP0p3uu5rQAQLc=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
|
||||
|
|
@ -1022,7 +998,6 @@ golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnf
|
|||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
|
@ -1033,7 +1008,6 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
|
@ -1079,7 +1053,6 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
@ -1160,7 +1133,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -1168,7 +1140,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -1256,7 +1227,6 @@ golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXR
|
|||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
@ -1276,7 +1246,6 @@ golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2M
|
|||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
|
|
@ -1294,7 +1263,6 @@ golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgw
|
|||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
|
@ -1517,7 +1485,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY=
|
||||
k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
|
||||
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
|
||||
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
|
||||
|
|
@ -1527,7 +1494,6 @@ k8s.io/api v0.22.4/go.mod h1:Rgs+9gIGYC5laXQSZZ9JqT5NevNgoGiOdVWi1BAB3qk=
|
|||
k8s.io/apiextensions-apiserver v0.22.1/go.mod h1:HeGmorjtRmRLE+Q8dJu6AYRoZccvCMsghwS8XTUYb2c=
|
||||
k8s.io/apiextensions-apiserver v0.22.4 h1:2iGpcVyw4MnAyyXVJU2Xg6ZsbIxAOfRHo0LF5A5J0RA=
|
||||
k8s.io/apiextensions-apiserver v0.22.4/go.mod h1:kH9lxD8dbJ+k0ZizGET55lFgdGjO8t45fgZnCVdZEpw=
|
||||
k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig=
|
||||
k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
||||
k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
||||
k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
|
||||
|
|
@ -1541,14 +1507,12 @@ k8s.io/apiserver v0.22.1/go.mod h1:2mcM6dzSt+XndzVQJX21Gx0/Klo7Aen7i0Ai6tIa400=
|
|||
k8s.io/apiserver v0.22.4/go.mod h1:38WmcUZiiy41A7Aty8/VorWRa8vDGqoUzDf2XYlku0E=
|
||||
k8s.io/cli-runtime v0.22.1 h1:WIueieKvT+IiSVSFosRLI6rkM0tyBGEGH1WUEztVjho=
|
||||
k8s.io/cli-runtime v0.22.1/go.mod h1:YqwGrlXeEk15Yn3em2xzr435UGwbrCw5x+COQoTYfoo=
|
||||
k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU=
|
||||
k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
|
||||
k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
|
||||
k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
|
||||
k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk=
|
||||
k8s.io/client-go v0.22.4 h1:aAQ1Wk+I3bjCNk35YWUqbaueqrIonkfDPJSPDDe8Kfg=
|
||||
k8s.io/client-go v0.22.4/go.mod h1:Yzw4e5e7h1LNHA4uqnMVrpEpUs1hJOiuBsJKIlRCHDA=
|
||||
k8s.io/code-generator v0.18.8/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
|
||||
k8s.io/code-generator v0.22.1/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o=
|
||||
k8s.io/code-generator v0.22.4 h1:h7lBa5IuEUC4OQ45q/gIip/a0iQcML2iwrRmXksau30=
|
||||
k8s.io/code-generator v0.22.4/go.mod h1:qjYl54pQ/emhkT0UxbufbREYJMWsHNNV/jSVwhYZQGw=
|
||||
|
|
@ -1562,15 +1526,9 @@ k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM=
|
|||
k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
||||
k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
||||
k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 h1:Uusb3oh8XcdzDF/ndlI4ToKTYVlkCSJP39SRY2mfRAw=
|
||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
|
|
@ -1579,7 +1537,6 @@ k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw=
|
|||
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-aggregator v0.22.4 h1:2aJMJMhWyKFRtVlj2ofGHewfjODXrMkjwkNlN1jn2jU=
|
||||
k8s.io/kube-aggregator v0.22.4/go.mod h1:nH2L1wiG9pMqYV7P8XIMb9RbIEZPBwxz0iJqPPrtALU=
|
||||
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
|
||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
||||
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c h1:jvamsI1tn9V0S8jicyX82qaFC0H/NKxv2e5mbqsgR80=
|
||||
|
|
@ -1587,7 +1544,6 @@ k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2R
|
|||
k8s.io/kubectl v0.22.1/go.mod h1:mjAOgEbMNMtZWxnfM6jd+nPjPsaoLqO5xanc78WcSbw=
|
||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||
k8s.io/metrics v0.22.1/go.mod h1:i/ZNap89UkV1gLa26dn7fhKAdheJaKy+moOqJbiif7E=
|
||||
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g=
|
||||
|
|
@ -1608,8 +1564,6 @@ sigs.k8s.io/kustomize/cmd/config v0.9.13/go.mod h1:7547FLF8W/lTaDf0BDqFTbZxM9zqw
|
|||
sigs.k8s.io/kustomize/kustomize/v4 v4.2.0/go.mod h1:MOkR6fmhwG7hEDRXBYELTi5GSFcLwfqwzTRHW3kv5go=
|
||||
sigs.k8s.io/kustomize/kyaml v0.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA=
|
||||
sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM=
|
||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno=
|
||||
|
|
|
|||
|
|
@ -2251,7 +2251,7 @@ func (hc *HealthChecker) checkMisconfiguredOpaquePortAnnotations(ctx context.Con
|
|||
// This is used instead of `hc.kubeAPI` to limit multiple k8s API requests
|
||||
// and use the caching logic in the shared informers
|
||||
// TODO: move the shared informer code out of `controller/`, and into `pkg` to simplify the dependency tree.
|
||||
kubeAPI := controllerK8s.NewAPI(hc.kubeAPI, nil, nil, nil, controllerK8s.Endpoint, controllerK8s.Pod, controllerK8s.Svc)
|
||||
kubeAPI := controllerK8s.NewAPI(hc.kubeAPI, nil, nil, controllerK8s.Endpoint, controllerK8s.Pod, controllerK8s.Svc)
|
||||
kubeAPI.Sync(ctx.Done())
|
||||
|
||||
services, err := kubeAPI.Svc().Lister().Services(hc.DataPlaneNamespace).List(labels.Everything())
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import (
|
|||
|
||||
crdclient "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned"
|
||||
"github.com/linkerd/linkerd2/pkg/prometheus"
|
||||
tsclient "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
|
|
@ -40,7 +39,6 @@ type KubernetesAPI struct {
|
|||
kubernetes.Interface
|
||||
Apiextensions apiextensionsclient.Interface // for CRDs
|
||||
Apiregistration apiregistration.Interface // for access to APIService
|
||||
TsClient tsclient.Interface
|
||||
DynamicClient dynamic.Interface
|
||||
L5dCrdClient crdclient.Interface
|
||||
}
|
||||
|
|
@ -85,10 +83,6 @@ func NewAPIForConfig(config *rest.Config, impersonate string, impersonateGroup [
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("error configuring Kubernetes API server aggregator: %v", err)
|
||||
}
|
||||
tsClient, err := tsclient.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error configuring Traffic Split clientset: %v", err)
|
||||
}
|
||||
dynamicClient, err := dynamic.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error configuring Kubernetes Dynamic Client: %v", err)
|
||||
|
|
@ -104,7 +98,6 @@ func NewAPIForConfig(config *rest.Config, impersonate string, impersonateGroup [
|
|||
Interface: clientset,
|
||||
Apiextensions: apiextensions,
|
||||
Apiregistration: aggregatorClient,
|
||||
TsClient: tsClient,
|
||||
DynamicClient: dynamicClient,
|
||||
L5dCrdClient: l5dCrdClient,
|
||||
}, nil
|
||||
|
|
|
|||
|
|
@ -7,11 +7,8 @@ import (
|
|||
|
||||
spclient "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned"
|
||||
spfake "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/fake"
|
||||
tsclient "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned"
|
||||
tsfake "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned/fake"
|
||||
|
||||
spscheme "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/scheme"
|
||||
tsscheme "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned/scheme"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
discovery "k8s.io/api/discovery/v1beta1"
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
|
|
@ -34,7 +31,7 @@ import (
|
|||
|
||||
// NewFakeAPI provides a mock KubernetesAPI backed by hard-coded resources
|
||||
func NewFakeAPI(configs ...string) (*KubernetesAPI, error) {
|
||||
client, apiextClient, apiregClient, _, _, err := NewFakeClientSets(configs...)
|
||||
client, apiextClient, apiregClient, _, err := NewFakeClientSets(configs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -50,7 +47,7 @@ func NewFakeAPI(configs ...string) (*KubernetesAPI, error) {
|
|||
// NewFakeAPIFromManifests reads from a slice of readers, each representing a
|
||||
// manifest or collection of manifests, and returns a mock KubernetesAPI.
|
||||
func NewFakeAPIFromManifests(readers []io.Reader) (*KubernetesAPI, error) {
|
||||
client, apiextClient, apiregClient, _, _, err := newFakeClientSetsFromManifests(readers)
|
||||
client, apiextClient, apiregClient, _, err := newFakeClientSetsFromManifests(readers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -69,7 +66,6 @@ func NewFakeClientSets(configs ...string) (
|
|||
apiextensionsclient.Interface,
|
||||
apiregistrationclient.Interface,
|
||||
spclient.Interface,
|
||||
tsclient.Interface,
|
||||
error,
|
||||
) {
|
||||
objs := []runtime.Object{}
|
||||
|
|
@ -77,11 +73,10 @@ func NewFakeClientSets(configs ...string) (
|
|||
apiRegObjs := []runtime.Object{}
|
||||
discoveryObjs := []runtime.Object{}
|
||||
spObjs := []runtime.Object{}
|
||||
tsObjs := []runtime.Object{}
|
||||
for _, config := range configs {
|
||||
obj, err := ToRuntimeObject(config)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
switch strings.ToLower(obj.GetObjectKind().GroupVersionKind().Kind) {
|
||||
case "customresourcedefinition":
|
||||
|
|
@ -92,8 +87,6 @@ func NewFakeClientSets(configs ...string) (
|
|||
discoveryObjs = append(discoveryObjs, obj)
|
||||
case ServiceProfile:
|
||||
spObjs = append(spObjs, obj)
|
||||
case TrafficSplit:
|
||||
tsObjs = append(tsObjs, obj)
|
||||
default:
|
||||
objs = append(objs, obj)
|
||||
}
|
||||
|
|
@ -105,7 +98,7 @@ metadata:
|
|||
name: kubernetes
|
||||
namespace: default`)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
objs = append(objs, endpointslice)
|
||||
|
||||
|
|
@ -134,7 +127,6 @@ metadata:
|
|||
apiextensionsfake.NewSimpleClientset(apiextObjs...),
|
||||
apiregistrationfake.NewSimpleClientset(apiRegObjs...),
|
||||
spfake.NewSimpleClientset(spObjs...),
|
||||
tsfake.NewSimpleClientset(tsObjs...),
|
||||
nil
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +139,6 @@ func newFakeClientSetsFromManifests(readers []io.Reader) (
|
|||
apiextensionsclient.Interface,
|
||||
apiregistrationclient.Interface,
|
||||
spclient.Interface,
|
||||
tsclient.Interface,
|
||||
error,
|
||||
) {
|
||||
configs := []string{}
|
||||
|
|
@ -163,13 +154,13 @@ func newFakeClientSetsFromManifests(readers []io.Reader) (
|
|||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
// check for kind
|
||||
var typeMeta metav1.TypeMeta
|
||||
if err := yaml.Unmarshal(bytes, &typeMeta); err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
switch typeMeta.Kind {
|
||||
|
|
@ -179,7 +170,7 @@ func newFakeClientSetsFromManifests(readers []io.Reader) (
|
|||
case "List":
|
||||
var sourceList corev1.List
|
||||
if err := yaml.Unmarshal(bytes, &sourceList); err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
for _, item := range sourceList.Items {
|
||||
configs = append(configs, string(item.Raw))
|
||||
|
|
@ -199,7 +190,6 @@ func ToRuntimeObject(config string) (runtime.Object, error) {
|
|||
apiextensionsv1beta1.AddToScheme(scheme.Scheme)
|
||||
apiregistrationv1.AddToScheme(scheme.Scheme)
|
||||
spscheme.AddToScheme(scheme.Scheme)
|
||||
tsscheme.AddToScheme(scheme.Scheme)
|
||||
decode := scheme.Codecs.UniversalDeserializer().Decode
|
||||
obj, _, err := decode([]byte(config), nil, nil)
|
||||
return obj, err
|
||||
|
|
@ -213,6 +203,5 @@ func ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
|
|||
apiextensionsv1beta1.AddToScheme(scheme.Scheme)
|
||||
apiregistrationv1.AddToScheme(scheme.Scheme)
|
||||
spscheme.AddToScheme(scheme.Scheme)
|
||||
tsscheme.AddToScheme(scheme.Scheme)
|
||||
return scheme.Scheme.ObjectKinds(obj)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ spec:
|
|||
tc := tc // pin
|
||||
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
_, _, _, _, _, err := NewFakeClientSets(tc.k8sConfigs...)
|
||||
_, _, _, _, err := NewFakeClientSets(tc.k8sConfigs...)
|
||||
if !reflect.DeepEqual(err, tc.err) {
|
||||
t.Fatalf("Expected error: %s, Got: %s", tc.err, err)
|
||||
}
|
||||
|
|
@ -330,7 +330,7 @@ spec:
|
|||
readers = append(readers, strings.NewReader(m))
|
||||
}
|
||||
|
||||
_, _, _, _, _, err := newFakeClientSetsFromManifests(readers)
|
||||
_, _, _, _, err := newFakeClientSetsFromManifests(readers)
|
||||
if !reflect.DeepEqual(err, tc.err) {
|
||||
t.Fatalf("Expected error: %s, Got: %s", tc.err, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ const (
|
|||
Service = "service"
|
||||
ServiceProfile = "serviceprofile"
|
||||
StatefulSet = "statefulset"
|
||||
TrafficSplit = "trafficsplit"
|
||||
Node = "node"
|
||||
Server = "server"
|
||||
ServerAuthorization = "serverauthorization"
|
||||
|
|
@ -65,7 +64,6 @@ var AllResources = []string{
|
|||
Server,
|
||||
ServerAuthorization,
|
||||
StatefulSet,
|
||||
TrafficSplit,
|
||||
}
|
||||
|
||||
// StatAllResourceTypes represents the resources to query in StatSummary when Resource.Type is "all"
|
||||
|
|
@ -77,7 +75,6 @@ var StatAllResourceTypes = []string{
|
|||
ReplicationController,
|
||||
Pod,
|
||||
Service,
|
||||
TrafficSplit,
|
||||
Authority,
|
||||
CronJob,
|
||||
ReplicaSet,
|
||||
|
|
@ -93,7 +90,6 @@ var CompletionResourceTypes = []string{
|
|||
ReplicationController,
|
||||
Pod,
|
||||
Service,
|
||||
TrafficSplit,
|
||||
Authority,
|
||||
CronJob,
|
||||
ReplicaSet,
|
||||
|
|
@ -114,7 +110,6 @@ var resourceNames = []resourceName{
|
|||
{"saz", "serverauthorization", "serverauthorizations"},
|
||||
{"srv", "server", "servers"},
|
||||
{"sts", "statefulset", "statefulsets"},
|
||||
{"ts", "trafficsplit", "trafficsplits"},
|
||||
{"ln", "link", "links"},
|
||||
{"all", "all", "all"},
|
||||
}
|
||||
|
|
@ -186,8 +181,6 @@ func ShortNameFromCanonicalResourceName(canonicalName string) string {
|
|||
return "sp"
|
||||
case StatefulSet:
|
||||
return "sts"
|
||||
case TrafficSplit:
|
||||
return "ts"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,161 +0,0 @@
|
|||
package smimetrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/linkerd/linkerd2/testutil"
|
||||
"github.com/servicemeshinterface/smi-sdk-go/pkg/apis/metrics/v1alpha1"
|
||||
)
|
||||
|
||||
var TestHelper *testutil.TestHelper
|
||||
|
||||
//nolint // The test that uses this is currently skipped.
|
||||
type testCase struct {
|
||||
name string
|
||||
kind string
|
||||
// edges > 0 denotes that its a edges query, otherwise a resource query
|
||||
edges int
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
TestHelper = testutil.NewTestHelper()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestSMIMetrics(t *testing.T) {
|
||||
|
||||
t.Skip("Skipped, as SMI-Metrics currently hardcodes the prometheusUrl of Linkerd which changed")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if os.Getenv("RUN_ARM_TEST") != "" {
|
||||
t.Skip("Skipped. SMI-metrics image does not support ARM yet")
|
||||
}
|
||||
|
||||
// Install smi-metrics using Helm chart
|
||||
testNamespace := TestHelper.GetTestNamespace("smi-metrics-test")
|
||||
err := TestHelper.CreateDataPlaneNamespaceIfNotExists(ctx, testNamespace, nil)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "failed to create %s namespace: %s", testNamespace, err)
|
||||
}
|
||||
|
||||
// Currently, SMI-Metrics Helm chart is saved locally and can be updated to a newer version
|
||||
// by downloading from https://github.com/servicemeshinterface/smi-metrics/releases and
|
||||
// moving the package here, along with a version bump below
|
||||
args := []string{
|
||||
"install",
|
||||
"smi-metrics",
|
||||
"smi-metrics-0.2.1.tgz",
|
||||
"--set",
|
||||
"adapter=linkerd",
|
||||
"--namespace",
|
||||
testNamespace,
|
||||
}
|
||||
|
||||
if stdout, stderr, err := TestHelper.HelmRun(args...); err != nil {
|
||||
testutil.AnnotatedFatalf(t, "'helm install' command failed\n%s\n%s\n%v", stdout, stderr, err)
|
||||
}
|
||||
|
||||
if err := TestHelper.CheckPods(ctx, testNamespace, "smi-metrics", 1); err != nil {
|
||||
if rce, ok := err.(*testutil.RestartCountError); ok {
|
||||
testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
|
||||
} else {
|
||||
testutil.AnnotatedError(t, "CheckPods timed-out", err)
|
||||
}
|
||||
}
|
||||
|
||||
testCases := []testCase{
|
||||
{
|
||||
name: "linkerd-destination",
|
||||
kind: "deployments",
|
||||
},
|
||||
{
|
||||
name: "linkerd-prometheus",
|
||||
kind: "deployments",
|
||||
},
|
||||
{
|
||||
name: "linkerd-destination",
|
||||
kind: "deployments",
|
||||
edges: 2,
|
||||
},
|
||||
{
|
||||
name: "linkerd-identity",
|
||||
kind: "deployments",
|
||||
edges: 1,
|
||||
},
|
||||
}
|
||||
|
||||
timeout := 50 * time.Second
|
||||
// check resource queries
|
||||
for _, tc := range testCases {
|
||||
tc := tc // pin
|
||||
err = TestHelper.RetryFor(timeout, func() error {
|
||||
|
||||
queryURL := fmt.Sprintf("/apis/metrics.smi-spec.io/v1alpha1/namespaces/%s/%s/%s", TestHelper.GetLinkerdNamespace(), tc.kind, tc.name)
|
||||
if tc.edges > 0 {
|
||||
queryURL += "/edges"
|
||||
}
|
||||
|
||||
queryArgs := []string{
|
||||
"get",
|
||||
"--raw",
|
||||
queryURL,
|
||||
}
|
||||
|
||||
out, err := TestHelper.Kubectl("", queryArgs...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to query smi-metrics URL %s: %s\n%s", queryURL, err, out)
|
||||
}
|
||||
|
||||
if tc.edges > 0 {
|
||||
// edges query
|
||||
var metrics v1alpha1.TrafficMetricsList
|
||||
err = json.Unmarshal([]byte(out), &metrics)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal output for query %s into TrafficMetricsList type: %s", queryURL, err)
|
||||
}
|
||||
|
||||
if err = checkTrafficMetricsList(metrics, tc.name, tc.edges); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
} else {
|
||||
// resource query
|
||||
var metrics v1alpha1.TrafficMetrics
|
||||
err = json.Unmarshal([]byte(out), &metrics)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal output for query %s into TrafficMetrics type: %s", queryURL, err)
|
||||
}
|
||||
|
||||
if err = checkTrafficMetrics(metrics, tc.name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
testutil.AnnotatedError(t, fmt.Sprintf("timed-out checking smi-metrics output (%s)", timeout), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkTrafficMetrics(metrics v1alpha1.TrafficMetrics, name string) error {
|
||||
if metrics.Name == name {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("expected %s, but got %s", name, metrics.Name)
|
||||
|
||||
}
|
||||
|
||||
func checkTrafficMetricsList(metrics v1alpha1.TrafficMetricsList, name string, numberOfEdges int) error {
|
||||
if metrics.Resource.Name == name && len(metrics.Items) == numberOfEdges {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("expected %s with %d edges, but got %s with %d edges", name, numberOfEdges, metrics.Resource.Name, len(metrics.Items))
|
||||
}
|
||||
|
|
@ -13,63 +13,11 @@ import (
|
|||
|
||||
var TestHelper *testutil.TestHelper
|
||||
|
||||
const zeroRPS = "0.0rps"
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
TestHelper = testutil.NewTestHelper()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
type statTsRow struct {
|
||||
name string
|
||||
apex string
|
||||
leaf string
|
||||
weight string
|
||||
success string
|
||||
rps string
|
||||
latencyP50 string
|
||||
latencyP95 string
|
||||
latencyP99 string
|
||||
}
|
||||
|
||||
func parseStatTsRow(out string, expectedRowCount, expectedColumnCount int) (map[string]*statTsRow, error) {
|
||||
// remove extra warning when parsing stat ts output
|
||||
out = strings.TrimSuffix(out, "\n")
|
||||
out = strings.Join(strings.Split(out, "\n")[2:], "\n")
|
||||
rows, err := testutil.CheckRowCount(out, expectedRowCount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
statRows := make(map[string]*statTsRow)
|
||||
|
||||
for _, row := range rows {
|
||||
fields := strings.Fields(row)
|
||||
|
||||
if len(fields) != expectedColumnCount {
|
||||
return nil, fmt.Errorf(
|
||||
"Expected [%d] columns in stat output, got [%d]; full output:\n%s",
|
||||
expectedColumnCount, len(fields), row)
|
||||
}
|
||||
|
||||
row := &statTsRow{
|
||||
name: fields[0],
|
||||
apex: fields[1],
|
||||
leaf: fields[2],
|
||||
weight: fields[3],
|
||||
success: fields[4],
|
||||
rps: fields[5],
|
||||
latencyP50: fields[6],
|
||||
latencyP95: fields[7],
|
||||
latencyP99: fields[8],
|
||||
}
|
||||
|
||||
statRows[row.leaf] = row
|
||||
|
||||
}
|
||||
return statRows, nil
|
||||
}
|
||||
|
||||
func parseStatRows(out string, expectedRowCount, expectedColumnCount int) ([]*testutil.RowStat, error) {
|
||||
rows, err := testutil.CheckRowCount(out, expectedRowCount)
|
||||
if err != nil {
|
||||
|
|
@ -103,238 +51,6 @@ func parseStatRows(out string, expectedRowCount, expectedColumnCount int) ([]*te
|
|||
}
|
||||
return statRows, nil
|
||||
}
|
||||
func statTrafficSplit(from string, ns string) (map[string]*statTsRow, error) {
|
||||
cmd := []string{"viz", "stat", "ts", "--from", from, "--namespace", ns, "-t", "30s", "--unmeshed"}
|
||||
out, err := TestHelper.LinkerdRun(cmd...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parseStatTsRow(out, 2, 9)
|
||||
}
|
||||
|
||||
func validateTrafficSplit(actual *statTsRow, expected *statTsRow) error {
|
||||
|
||||
if actual.name != expected.name && expected.name != "" {
|
||||
return fmt.Errorf("expected name '%s' for leaf %s, got '%s'", expected.name, expected.leaf, actual.name)
|
||||
}
|
||||
|
||||
if actual.apex != expected.apex && expected.apex != "" {
|
||||
return fmt.Errorf("expected apex '%s' for leaf %s, got '%s'", expected.apex, expected.leaf, actual.apex)
|
||||
}
|
||||
|
||||
if actual.weight != expected.weight && expected.weight != "" {
|
||||
return fmt.Errorf("expected weight '%s' for leaf %s, got '%s'", expected.weight, expected.leaf, actual.weight)
|
||||
}
|
||||
|
||||
if actual.success != expected.success && expected.success != "" {
|
||||
return fmt.Errorf("expected success '%s' for leaf %s, got '%s'", expected.success, expected.leaf, actual.success)
|
||||
}
|
||||
|
||||
if expected.rps != "" {
|
||||
if expected.rps == "-" && actual.rps != "-" {
|
||||
return fmt.Errorf("expected no rps for leaf %s, got '%s'", expected.leaf, actual.rps)
|
||||
}
|
||||
|
||||
if expected.rps == zeroRPS && actual.rps != zeroRPS {
|
||||
return fmt.Errorf("expected zero rps for leaf %s, got '%s'", expected.leaf, actual.rps)
|
||||
}
|
||||
|
||||
if expected.rps != zeroRPS && actual.rps == zeroRPS {
|
||||
return fmt.Errorf("expected non zero rps for leaf %s, got '%s'", expected.leaf, actual.rps)
|
||||
}
|
||||
}
|
||||
|
||||
if actual.latencyP50 != expected.latencyP50 && expected.latencyP50 != "" {
|
||||
return fmt.Errorf("expected latencyP50 '%s' for leaf %s, got '%s'", expected.latencyP50, expected.leaf, actual.latencyP50)
|
||||
}
|
||||
|
||||
if actual.latencyP95 != expected.latencyP95 && expected.latencyP95 != "" {
|
||||
return fmt.Errorf("expected latencyP95 '%s' for leaf %s, got '%s'", expected.latencyP95, expected.leaf, actual.latencyP95)
|
||||
}
|
||||
|
||||
if actual.latencyP99 != expected.latencyP99 && expected.latencyP99 != "" {
|
||||
return fmt.Errorf("expected latencyP99 '%s' for leaf %s, got '%s'", expected.latencyP99, expected.leaf, actual.latencyP99)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateExpectedTsOutput(rows map[string]*statTsRow, expectedBackendSvc, expectedFailingSvc *statTsRow) error {
|
||||
backendSvcLeafKey := "backend-svc"
|
||||
backendFailingSvcLeafKey := "failing-svc"
|
||||
|
||||
backendRow, ok := rows[backendSvcLeafKey]
|
||||
if !ok {
|
||||
return fmt.Errorf("no stats found for [%s]", backendSvcLeafKey)
|
||||
}
|
||||
|
||||
if err := validateTrafficSplit(backendRow, expectedBackendSvc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
backendFailingRow, ok := rows[backendFailingSvcLeafKey]
|
||||
if !ok {
|
||||
return fmt.Errorf("no stats found for [%s]", backendFailingSvcLeafKey)
|
||||
}
|
||||
|
||||
if err := validateTrafficSplit(backendFailingRow, expectedFailingSvc); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTrafficSplitCli(t *testing.T) {
|
||||
|
||||
for _, version := range []string{"v1alpha1", "v1alpha2"} {
|
||||
// pin version variable
|
||||
version := version
|
||||
ctx := context.Background()
|
||||
TestHelper.WithDataPlaneNamespace(ctx, fmt.Sprintf("trafficsplit-test-%s", version), map[string]string{}, t, func(t *testing.T, prefixedNs string) {
|
||||
out, err := TestHelper.LinkerdRun("inject", "--manual", "testdata/application.yaml")
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatal(t, "'linkerd inject' command failed", err)
|
||||
}
|
||||
|
||||
out, err = TestHelper.KubectlApply(out, prefixedNs)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
|
||||
"'kubectl apply' command failed\n%s", out)
|
||||
}
|
||||
|
||||
TsResourceFile := fmt.Sprintf("testdata/%s/traffic-split-leaf-weights.yaml", version)
|
||||
TsResource, err := testutil.ReadFile(TsResourceFile)
|
||||
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "cannot read updated traffic split resource",
|
||||
"cannot read updated traffic split resource: %s, %s", TsResource, err)
|
||||
}
|
||||
|
||||
out, err = TestHelper.KubectlApply(TsResource, prefixedNs)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "failed to update traffic split resource",
|
||||
"failed to update traffic split resource: %s\n %s", err, out)
|
||||
}
|
||||
|
||||
// wait for deployments to start
|
||||
for _, deploy := range []string{"backend", "failing", "slow-cooker"} {
|
||||
if err := TestHelper.CheckPods(ctx, prefixedNs, deploy, 1); err != nil {
|
||||
if rce, ok := err.(*testutil.RestartCountError); ok {
|
||||
testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
|
||||
} else {
|
||||
testutil.AnnotatedError(t, "CheckPods timed-out", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t.Run(fmt.Sprintf("ensure traffic is sent to one backend only for %s", version), func(t *testing.T) {
|
||||
timeout := 40 * time.Second
|
||||
err := TestHelper.RetryFor(timeout, func() error {
|
||||
|
||||
rows, err := statTrafficSplit("deploy/slow-cooker", prefixedNs)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatal(t, "error ensuring traffic is sent to one backend only", err)
|
||||
}
|
||||
|
||||
var weight string
|
||||
if version == "v1alpha1" {
|
||||
weight = "500m"
|
||||
} else {
|
||||
weight = "500"
|
||||
}
|
||||
|
||||
expectedBackendSvcOutput := &statTsRow{
|
||||
name: "backend-traffic-split",
|
||||
apex: "backend-svc",
|
||||
leaf: "backend-svc",
|
||||
weight: weight,
|
||||
success: "100.00%",
|
||||
rps: "0.5rps",
|
||||
}
|
||||
expectedFailingSvcOutput := &statTsRow{
|
||||
name: "backend-traffic-split",
|
||||
apex: "backend-svc",
|
||||
leaf: "failing-svc",
|
||||
weight: "0",
|
||||
success: "-",
|
||||
rps: "-",
|
||||
latencyP50: "-",
|
||||
latencyP95: "-",
|
||||
latencyP99: "-",
|
||||
}
|
||||
|
||||
if err := validateExpectedTsOutput(rows, expectedBackendSvcOutput, expectedFailingSvcOutput); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatal(t, fmt.Sprintf("timed-out ensuring traffic is sent to one backend only (%s)", timeout), err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run(fmt.Sprintf("update traffic split resource with equal weights for %s", version), func(t *testing.T) {
|
||||
|
||||
updatedTsResourceFile := fmt.Sprintf("testdata/%s/updated-traffic-split-leaf-weights.yaml", version)
|
||||
updatedTsResource, err := testutil.ReadFile(updatedTsResourceFile)
|
||||
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "cannot read updated traffic split resource",
|
||||
"cannot read updated traffic split resource: %s, %s", updatedTsResource, err)
|
||||
}
|
||||
|
||||
out, err := TestHelper.KubectlApply(updatedTsResource, prefixedNs)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "failed to update traffic split resource",
|
||||
"failed to update traffic split resource: %s\n %s", err, out)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run(fmt.Sprintf("ensure traffic is sent to both backends for %s", version), func(t *testing.T) {
|
||||
timeout := 40 * time.Second
|
||||
err := TestHelper.RetryFor(timeout, func() error {
|
||||
rows, err := statTrafficSplit("deploy/slow-cooker", prefixedNs)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatal(t, "error ensuring traffic is sent to both backends", err)
|
||||
}
|
||||
|
||||
var weight string
|
||||
if version == "v1alpha1" {
|
||||
weight = "500m"
|
||||
} else {
|
||||
weight = "500"
|
||||
}
|
||||
|
||||
expectedBackendSvcOutput := &statTsRow{
|
||||
name: "backend-traffic-split",
|
||||
apex: "backend-svc",
|
||||
leaf: "backend-svc",
|
||||
weight: weight,
|
||||
success: "100.00%",
|
||||
rps: "0.5rps",
|
||||
}
|
||||
expectedFailingSvcOutput := &statTsRow{
|
||||
name: "backend-traffic-split",
|
||||
apex: "backend-svc",
|
||||
leaf: "failing-svc",
|
||||
weight: weight,
|
||||
success: "0.00%",
|
||||
rps: "0.5rps",
|
||||
}
|
||||
|
||||
if err := validateExpectedTsOutput(rows, expectedBackendSvcOutput, expectedFailingSvcOutput); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatal(t, fmt.Sprintf("timed-out ensuring traffic is sent to both backends (%s)", timeout), err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrafficSplitCliWithSP(t *testing.T) {
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["policy.linkerd.io"]
|
||||
resources: ["servers", "serverauthorizations"]
|
||||
verbs: ["list", "get"]
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ func NewCmdStat() *cobra.Command {
|
|||
* replicasets
|
||||
* replicationcontrollers
|
||||
* statefulsets
|
||||
* trafficsplits
|
||||
* authorities (not supported in --from)
|
||||
* services (not supported in --from)
|
||||
* servers (not supported in --from)
|
||||
|
|
@ -167,15 +166,6 @@ If no resource name is specified, displays stats about all resources of the spec
|
|||
# Get all services in all namespaces that receive calls from hello1 deployment in the test namespace.
|
||||
linkerd viz stat services --from deploy/hello1 --from-namespace test --all-namespaces
|
||||
|
||||
# Get all trafficsplits and their leaf services.
|
||||
linkerd viz stat ts
|
||||
|
||||
# Get the hello-split trafficsplit and its leaf services.
|
||||
linkerd viz stat ts/hello-split
|
||||
|
||||
# Get all trafficsplits and their leaf services, and metrics for any traffic coming to the leaf services from the hello1 deployment.
|
||||
linkerd viz stat ts --from deploy/hello1
|
||||
|
||||
# Get all namespaces that receive traffic from the default namespace.
|
||||
linkerd viz stat namespaces --from ns/default
|
||||
|
||||
|
|
@ -363,7 +353,7 @@ func statHasRequestData(stat *pb.BasicStats) bool {
|
|||
}
|
||||
|
||||
func isPodOwnerResource(typ string) bool {
|
||||
return typ != k8s.TrafficSplit && typ != k8s.Authority && typ != k8s.Service && typ != k8s.Server && typ != k8s.ServerAuthorization
|
||||
return typ != k8s.Authority && typ != k8s.Service && typ != k8s.Server && typ != k8s.ServerAuthorization
|
||||
}
|
||||
|
||||
func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer, options *statOptions) {
|
||||
|
|
@ -406,9 +396,6 @@ func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer,
|
|||
|
||||
namespace := r.Resource.Namespace
|
||||
key := fmt.Sprintf("%s/%s", namespace, name)
|
||||
if r.Resource.Type == k8s.TrafficSplit || (r.Resource.Type == k8s.Service && r.TsStats != nil) {
|
||||
key = fmt.Sprintf("%s/%s/%s", namespace, name, r.TsStats.Leaf)
|
||||
}
|
||||
|
||||
resourceKey := r.Resource.Type
|
||||
|
||||
|
|
@ -448,43 +435,6 @@ func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer,
|
|||
tcpWriteBytes: getByteRate(r.GetTcpStats().GetWriteBytesTotal(), r.TimeWindow),
|
||||
}
|
||||
}
|
||||
if r.TsStats != nil {
|
||||
if r.GetResource().GetType() == k8s.TrafficSplit {
|
||||
leaf := r.TsStats.Leaf
|
||||
apex := r.TsStats.Apex
|
||||
weight := r.TsStats.Weight
|
||||
|
||||
if len(leaf) > maxLeafLength {
|
||||
maxLeafLength = len(leaf)
|
||||
}
|
||||
|
||||
if len(apex) > maxApexLength {
|
||||
maxApexLength = len(apex)
|
||||
}
|
||||
|
||||
statTables[resourceKey][key].tsStats = &tsStats{
|
||||
apex: apex,
|
||||
leaf: leaf,
|
||||
weight: weight,
|
||||
}
|
||||
} else {
|
||||
dst := r.TsStats.Leaf
|
||||
weight := r.TsStats.Weight
|
||||
|
||||
if len(dst) > maxDstLength {
|
||||
maxDstLength = len(dst)
|
||||
}
|
||||
|
||||
if len(weight) > maxWeightLength {
|
||||
maxWeightLength = len(weight)
|
||||
}
|
||||
|
||||
statTables[resourceKey][key].dstStats = &dstStats{
|
||||
dst: dst,
|
||||
weight: weight,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if r.SrvStats != nil {
|
||||
statTables[resourceKey][key].srvStats = &srvStats{
|
||||
|
|
@ -533,7 +483,7 @@ func showTCPBytes(options *statOptions, resourceType string) bool {
|
|||
}
|
||||
|
||||
func showTCPConns(resourceType string) bool {
|
||||
return resourceType != k8s.Authority && resourceType != k8s.TrafficSplit && resourceType != k8s.ServerAuthorization
|
||||
return resourceType != k8s.Authority && resourceType != k8s.ServerAuthorization
|
||||
}
|
||||
|
||||
func printSingleStatTable(stats map[string]*row, resourceTypeLabel, resourceType string, w *tabwriter.Writer, maxNameLength, maxNamespaceLength, maxLeafLength, maxApexLength, maxDstLength, maxWeightLength int, options *statOptions) {
|
||||
|
|
@ -779,9 +729,7 @@ func printStatJSON(statTables map[string]map[string]*row, w *tabwriter.Writer) {
|
|||
Kind: resourceType,
|
||||
Name: name,
|
||||
}
|
||||
if resourceType != k8s.TrafficSplit {
|
||||
entry.Meshed = stats[key].meshed
|
||||
}
|
||||
|
||||
if stats[key].rowStats != nil {
|
||||
entry.Success = &stats[key].successRate
|
||||
entry.Rps = &stats[key].requestRate
|
||||
|
|
@ -887,22 +835,9 @@ func buildStatSummaryRequests(resources []string, options *statOptions) ([]*pb.S
|
|||
requests = append(requests, req)
|
||||
}
|
||||
|
||||
if containsTS(targets) {
|
||||
fmt.Printf("Starting in 2.12, the SMI extension will be required for traffic splitting. Please follow the SMI extension getting started guide from https://linkerd.io/2.10/tasks/linkerd-smi\n\n")
|
||||
}
|
||||
|
||||
return requests, nil
|
||||
}
|
||||
|
||||
func containsTS(resources []*pb.Resource) bool {
|
||||
for _, resource := range resources {
|
||||
if resource.Type == k8s.TrafficSplit {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func sortStatsKeys(stats map[string]*row) []string {
|
||||
var sortedKeys []string
|
||||
for key := range stats {
|
||||
|
|
|
|||
|
|
@ -44,14 +44,6 @@ func TestStat(t *testing.T) {
|
|||
}, k8s.Pod, t)
|
||||
})
|
||||
|
||||
t.Run("Returns trafficsplit stats", func(t *testing.T) {
|
||||
testStatCall(paramsExp{
|
||||
options: options,
|
||||
resNs: []string{"default"},
|
||||
file: "stat_one_ts_output.golden",
|
||||
}, k8s.TrafficSplit, t)
|
||||
})
|
||||
|
||||
options.outputFormat = jsonOutput
|
||||
t.Run("Returns namespace stats (json)", func(t *testing.T) {
|
||||
testStatCall(paramsExp{
|
||||
|
|
@ -66,14 +58,6 @@ func TestStat(t *testing.T) {
|
|||
}, k8s.Namespace, t)
|
||||
})
|
||||
|
||||
t.Run("Returns trafficsplit stats (json)", func(t *testing.T) {
|
||||
testStatCall(paramsExp{
|
||||
options: options,
|
||||
resNs: []string{"default"},
|
||||
file: "stat_one_ts_output_json.golden",
|
||||
}, k8s.TrafficSplit, t)
|
||||
})
|
||||
|
||||
options = newStatOptions()
|
||||
options.allNamespaces = true
|
||||
t.Run("Returns all namespace stats", func(t *testing.T) {
|
||||
|
|
@ -230,20 +214,13 @@ func TestStat(t *testing.T) {
|
|||
func testStatCall(exp paramsExp, resourceType string, t *testing.T) {
|
||||
mockClient := &api.MockAPIClient{}
|
||||
response := api.GenStatSummaryResponse("emoji", resourceType, exp.resNs, exp.counts, true, true)
|
||||
if resourceType == k8s.TrafficSplit {
|
||||
response = api.GenStatTsResponse("foo-split", resourceType, exp.resNs, true, true)
|
||||
}
|
||||
|
||||
mockClient.StatSummaryResponseToReturn = response
|
||||
|
||||
args := []string{"ns"}
|
||||
if resourceType == k8s.TrafficSplit {
|
||||
args = []string{"trafficsplit"}
|
||||
}
|
||||
if exp.options.namespace == "" {
|
||||
exp.options.namespace = pkgcmd.GetDefaultNamespace(kubeconfigPath, kubeContext)
|
||||
}
|
||||
reqs, err := buildStatSummaryRequests(args, exp.options)
|
||||
reqs, err := buildStatSummaryRequests([]string{"ns"}, exp.options)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["policy.linkerd.io"]
|
||||
resources: ["servers", "serverauthorizations"]
|
||||
verbs: ["list", "get"]
|
||||
|
|
@ -503,7 +500,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 951a7b61ff59229914ca604c671353e5fdc0eda710bde2bfbb50c9225225babe
|
||||
checksum/config: ae930acf3edba3cbf32c43dacfa4808bf679c5c932870cb2a2a46de1023f01c8
|
||||
linkerd.io/created-by: linkerd/helm dev-undefined
|
||||
labels:
|
||||
linkerd.io/extension: viz
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["policy.linkerd.io"]
|
||||
resources: ["servers", "serverauthorizations"]
|
||||
verbs: ["list", "get"]
|
||||
|
|
@ -503,7 +500,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 951a7b61ff59229914ca604c671353e5fdc0eda710bde2bfbb50c9225225babe
|
||||
checksum/config: ae930acf3edba3cbf32c43dacfa4808bf679c5c932870cb2a2a46de1023f01c8
|
||||
linkerd.io/created-by: linkerd/helm dev-undefined
|
||||
labels:
|
||||
linkerd.io/extension: viz
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["policy.linkerd.io"]
|
||||
resources: ["servers", "serverauthorizations"]
|
||||
verbs: ["list", "get"]
|
||||
|
|
@ -490,7 +487,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 951a7b61ff59229914ca604c671353e5fdc0eda710bde2bfbb50c9225225babe
|
||||
checksum/config: ae930acf3edba3cbf32c43dacfa4808bf679c5c932870cb2a2a46de1023f01c8
|
||||
linkerd.io/created-by: linkerd/helm dev-undefined
|
||||
labels:
|
||||
linkerd.io/extension: viz
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["policy.linkerd.io"]
|
||||
resources: ["servers", "serverauthorizations"]
|
||||
verbs: ["list", "get"]
|
||||
|
|
@ -463,7 +460,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 951a7b61ff59229914ca604c671353e5fdc0eda710bde2bfbb50c9225225babe
|
||||
checksum/config: ae930acf3edba3cbf32c43dacfa4808bf679c5c932870cb2a2a46de1023f01c8
|
||||
linkerd.io/created-by: linkerd/helm dev-undefined
|
||||
labels:
|
||||
linkerd.io/extension: viz
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["policy.linkerd.io"]
|
||||
resources: ["servers", "serverauthorizations"]
|
||||
verbs: ["list", "get"]
|
||||
|
|
@ -503,7 +500,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 951a7b61ff59229914ca604c671353e5fdc0eda710bde2bfbb50c9225225babe
|
||||
checksum/config: ae930acf3edba3cbf32c43dacfa4808bf679c5c932870cb2a2a46de1023f01c8
|
||||
linkerd.io/created-by: linkerd/helm dev-undefined
|
||||
labels:
|
||||
linkerd.io/extension: viz
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ rules:
|
|||
- apiGroups: ["linkerd.io"]
|
||||
resources: ["serviceprofiles"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["split.smi-spec.io"]
|
||||
resources: ["trafficsplits"]
|
||||
verbs: ["list", "get", "watch"]
|
||||
- apiGroups: ["policy.linkerd.io"]
|
||||
resources: ["servers", "serverauthorizations"]
|
||||
verbs: ["list", "get"]
|
||||
|
|
@ -503,7 +500,7 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: 951a7b61ff59229914ca604c671353e5fdc0eda710bde2bfbb50c9225225babe
|
||||
checksum/config: ae930acf3edba3cbf32c43dacfa4808bf679c5c932870cb2a2a46de1023f01c8
|
||||
linkerd.io/created-by: linkerd/helm dev-undefined
|
||||
labels:
|
||||
linkerd.io/extension: viz
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"namespace": "emojivoto1",
|
||||
"kind": "namespace",
|
||||
"name": "emoji",
|
||||
"meshed": "1/2",
|
||||
"success": 1,
|
||||
"rps": 2.05,
|
||||
"latency_ms_p50": 123,
|
||||
|
|
@ -17,7 +16,6 @@
|
|||
"namespace": "emojivoto2",
|
||||
"kind": "namespace",
|
||||
"name": "emoji",
|
||||
"meshed": "1/2",
|
||||
"success": 1,
|
||||
"rps": 2.05,
|
||||
"latency_ms_p50": 123,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"namespace": "emojivoto1",
|
||||
"kind": "namespace",
|
||||
"name": "emoji",
|
||||
"meshed": "1/2",
|
||||
"success": 1,
|
||||
"rps": 2.05,
|
||||
"latency_ms_p50": 123,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ func main() {
|
|||
ctx,
|
||||
*kubeConfigPath,
|
||||
true,
|
||||
k8s.CJ, k8s.DS, k8s.Deploy, k8s.Job, k8s.NS, k8s.Pod, k8s.RC, k8s.RS, k8s.Svc, k8s.SS, k8s.SP, k8s.TS,
|
||||
k8s.CJ, k8s.DS, k8s.Deploy, k8s.Job, k8s.NS, k8s.Pod, k8s.RC, k8s.RS, k8s.Svc, k8s.SS, k8s.SP,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to initialize K8s API: %s", err)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import (
|
|||
pb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
|
||||
vizutil "github.com/linkerd/linkerd2/viz/pkg/util"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/servicemeshinterface/smi-sdk-go/pkg/apis/split/v1alpha1"
|
||||
log "github.com/sirupsen/logrus"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
|
@ -39,15 +38,6 @@ type rKey struct {
|
|||
Name string
|
||||
}
|
||||
|
||||
type tsKey struct {
|
||||
Namespace string
|
||||
Type string
|
||||
Name string
|
||||
Apex string
|
||||
Leaf string
|
||||
Weight string
|
||||
}
|
||||
|
||||
type dstKey struct {
|
||||
Namespace string
|
||||
Service string
|
||||
|
|
@ -78,12 +68,6 @@ type podStats struct {
|
|||
errors map[string]*pb.PodErrors
|
||||
}
|
||||
|
||||
type trafficSplitStats struct {
|
||||
namespace string
|
||||
name string
|
||||
apex string
|
||||
}
|
||||
|
||||
func (s *grpcServer) StatSummary(ctx context.Context, req *pb.StatSummaryRequest) (*pb.StatSummaryResponse, error) {
|
||||
|
||||
// check for well-formed request
|
||||
|
|
@ -133,8 +117,6 @@ func (s *grpcServer) StatSummary(ctx context.Context, req *pb.StatSummaryRequest
|
|||
resultChan <- s.nonK8sResourceQuery(ctx, statReq)
|
||||
} else if statReq.GetSelector().GetResource().GetType() == k8s.Service {
|
||||
resultChan <- s.serviceResourceQuery(ctx, statReq)
|
||||
} else if isTrafficSplitQuery(statReq.GetSelector().GetResource().GetType()) {
|
||||
resultChan <- s.trafficSplitResourceQuery(ctx, statReq)
|
||||
} else if isPolicyResource(statReq.GetSelector().GetResource()) {
|
||||
resultChan <- s.policyResourceQuery(ctx, statReq)
|
||||
} else {
|
||||
|
|
@ -291,101 +273,6 @@ func (s *grpcServer) k8sResourceQuery(ctx context.Context, req *pb.StatSummaryRe
|
|||
return resourceResult{res: &rsp, err: nil}
|
||||
}
|
||||
|
||||
func (s *grpcServer) getTrafficSplits(req *pb.StatSummaryRequest) ([]*v1alpha1.TrafficSplit, error) {
|
||||
var err error
|
||||
var trafficSplits []*v1alpha1.TrafficSplit
|
||||
|
||||
res := req.GetSelector().GetResource()
|
||||
labelSelector, err := getLabelSelector(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.GetNamespace() == "" {
|
||||
trafficSplits, err = s.k8sAPI.TS().Lister().List(labelSelector)
|
||||
} else if res.GetName() == "" {
|
||||
trafficSplits, err = s.k8sAPI.TS().Lister().TrafficSplits(res.GetNamespace()).List(labelSelector)
|
||||
} else {
|
||||
var ts *v1alpha1.TrafficSplit
|
||||
ts, err = s.k8sAPI.TS().Lister().TrafficSplits(res.GetNamespace()).Get(res.GetName())
|
||||
trafficSplits = []*v1alpha1.TrafficSplit{ts}
|
||||
}
|
||||
|
||||
return trafficSplits, err
|
||||
}
|
||||
|
||||
func (s *grpcServer) trafficSplitResourceQuery(ctx context.Context, req *pb.StatSummaryRequest) resourceResult {
|
||||
|
||||
tss, err := s.getTrafficSplits(req)
|
||||
if err != nil {
|
||||
return resourceResult{res: nil, err: err}
|
||||
}
|
||||
|
||||
tsBasicStats := make(map[tsKey]*pb.BasicStats)
|
||||
rows := make([]*pb.StatTable_PodGroup_Row, 0)
|
||||
|
||||
for _, ts := range tss {
|
||||
backends := ts.Spec.Backends
|
||||
|
||||
tsStats := &trafficSplitStats{
|
||||
namespace: ts.ObjectMeta.Namespace,
|
||||
name: ts.ObjectMeta.Name,
|
||||
apex: ts.Spec.Service,
|
||||
}
|
||||
|
||||
if !req.SkipStats {
|
||||
tsBasicStats, err = s.getTrafficSplitMetrics(ctx, req, tsStats, req.TimeWindow)
|
||||
if err != nil {
|
||||
return resourceResult{res: nil, err: err}
|
||||
}
|
||||
}
|
||||
|
||||
for _, backend := range backends {
|
||||
name := backend.Service
|
||||
weight := backend.Weight.String()
|
||||
|
||||
currentLeaf := tsKey{
|
||||
Namespace: tsStats.namespace,
|
||||
Type: k8s.TrafficSplit,
|
||||
Name: tsStats.name,
|
||||
Apex: tsStats.apex,
|
||||
Leaf: name,
|
||||
}
|
||||
|
||||
trafficSplitStats := &pb.TrafficSplitStats{
|
||||
Apex: tsStats.apex,
|
||||
Leaf: name,
|
||||
Weight: weight,
|
||||
}
|
||||
|
||||
row := pb.StatTable_PodGroup_Row{
|
||||
Resource: &pb.Resource{
|
||||
Name: tsStats.name,
|
||||
Namespace: tsStats.namespace,
|
||||
Type: req.GetSelector().GetResource().GetType(),
|
||||
},
|
||||
TimeWindow: req.TimeWindow,
|
||||
Stats: tsBasicStats[currentLeaf],
|
||||
TsStats: trafficSplitStats,
|
||||
}
|
||||
rows = append(rows, &row)
|
||||
}
|
||||
}
|
||||
|
||||
// sort rows before returning in order to have a consistent order for tests
|
||||
rows = sortTrafficSplitRows(rows)
|
||||
|
||||
rsp := pb.StatTable{
|
||||
Table: &pb.StatTable_PodGroup_{
|
||||
PodGroup: &pb.StatTable_PodGroup{
|
||||
Rows: rows,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return resourceResult{res: &rsp, err: nil}
|
||||
}
|
||||
|
||||
func (s *grpcServer) getPolicyResourceKeys(req *pb.StatSummaryRequest) ([]rKey, error) {
|
||||
var err error
|
||||
var unstructuredResources *unstructured.UnstructuredList
|
||||
|
|
@ -597,10 +484,6 @@ func isNonK8sResourceQuery(resourceType string) bool {
|
|||
return resourceType == k8s.Authority
|
||||
}
|
||||
|
||||
func isTrafficSplitQuery(resourceType string) bool {
|
||||
return resourceType == k8s.TrafficSplit
|
||||
}
|
||||
|
||||
// get the list of objects for which we want to return results
|
||||
func getResultKeys(
|
||||
req *pb.StatSummaryRequest,
|
||||
|
|
@ -755,39 +638,6 @@ func (s *grpcServer) getStatMetrics(ctx context.Context, req *pb.StatSummaryRequ
|
|||
return basicStats, tcpStats, nil
|
||||
}
|
||||
|
||||
func (s *grpcServer) getTrafficSplitMetrics(ctx context.Context, req *pb.StatSummaryRequest, tsStats *trafficSplitStats, timeWindow string) (map[tsKey]*pb.BasicStats, error) {
|
||||
tsBasicStats := make(map[tsKey]*pb.BasicStats)
|
||||
labels, groupBy := buildServiceRequestLabels(req)
|
||||
|
||||
apex := tsStats.apex
|
||||
namespace := tsStats.namespace
|
||||
// TODO: add cluster domain to stringToMatch
|
||||
stringToMatch := fmt.Sprintf("%s.%s.svc", apex, namespace)
|
||||
|
||||
reqLabels := generateLabelStringWithRegex(labels, string(authorityLabel), stringToMatch)
|
||||
|
||||
promQueries := map[promType]string{
|
||||
promRequests: fmt.Sprintf(reqQuery, reqLabels, timeWindow, groupBy.String()),
|
||||
}
|
||||
quantileQueries := generateQuantileQueries(latencyQuantileQuery, reqLabels, timeWindow, groupBy.String())
|
||||
results, err := s.getPrometheusMetrics(ctx, promQueries, quantileQueries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
basicStats, _, _ := processPrometheusMetrics(req, results, groupBy) // we don't need tcpStat info for traffic split
|
||||
|
||||
for rKey, basicStatsVal := range basicStats {
|
||||
tsBasicStats[tsKey{
|
||||
Namespace: namespace,
|
||||
Name: tsStats.name,
|
||||
Type: req.Selector.Resource.Type,
|
||||
Apex: apex,
|
||||
Leaf: rKey.Name,
|
||||
}] = basicStatsVal
|
||||
}
|
||||
return tsBasicStats, nil
|
||||
}
|
||||
|
||||
func (s *grpcServer) getServiceMetrics(ctx context.Context, req *pb.StatSummaryRequest, timeWindow string) (map[dstKey]*pb.BasicStats, map[dstKey]*pb.TcpStats, error) {
|
||||
dstBasicStats := make(map[dstKey]*pb.BasicStats)
|
||||
dstTCPStats := make(map[dstKey]*pb.TcpStats)
|
||||
|
|
|
|||
|
|
@ -47,22 +47,6 @@ func genPromSample(resName string, resType string, resNs string, isDst bool) *mo
|
|||
}
|
||||
}
|
||||
|
||||
func genTrafficSplitPromSample(resName, resNs string) *model.Sample {
|
||||
labelName := model.LabelName("dst_service")
|
||||
namespaceLabel := model.LabelName("namespace")
|
||||
|
||||
return &model.Sample{
|
||||
Metric: model.Metric{
|
||||
labelName: model.LabelValue(resName),
|
||||
namespaceLabel: model.LabelValue(resNs),
|
||||
"classification": model.LabelValue("success"),
|
||||
"tls": model.LabelValue("false"),
|
||||
},
|
||||
Value: 123,
|
||||
Timestamp: 456,
|
||||
}
|
||||
}
|
||||
|
||||
func genEmptyResponse() *pb.StatSummaryResponse {
|
||||
return &pb.StatSummaryResponse{
|
||||
Response: &pb.StatSummaryResponse_Ok_{ // https://github.com/golang/protobuf/issues/205
|
||||
|
|
@ -645,78 +629,6 @@ status:
|
|||
testStatSummary(t, expectations)
|
||||
})
|
||||
|
||||
t.Run("Successfully performs a query based on resource type TrafficSplit", func(t *testing.T) {
|
||||
expectations := []statSumExpected{
|
||||
{
|
||||
expectedStatRPC: expectedStatRPC{
|
||||
err: nil,
|
||||
k8sConfigs: []string{`
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-1
|
||||
namespace: default
|
||||
labels:
|
||||
app: authors
|
||||
project: booksapp
|
||||
spec:
|
||||
selector:
|
||||
app: authors
|
||||
clusterIP: None
|
||||
ports:
|
||||
- name: service
|
||||
port: 7001
|
||||
`, `
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-2
|
||||
namespace: default
|
||||
labels:
|
||||
app: authors-clone
|
||||
project: booksapp
|
||||
spec:
|
||||
selector:
|
||||
app: authors-clone
|
||||
clusterIP: None
|
||||
ports:
|
||||
- name: service
|
||||
port: 7009
|
||||
`, `
|
||||
apiVersion: split.smi-spec.io/v1alpha1
|
||||
kind: TrafficSplit
|
||||
metadata:
|
||||
name: authors-split
|
||||
namespace: default
|
||||
spec:
|
||||
service: apex_name
|
||||
backends:
|
||||
- service: service-1
|
||||
weight: 900m
|
||||
- service: service-2
|
||||
weight: 100m
|
||||
`,
|
||||
},
|
||||
mockPromResponse: model.Vector{
|
||||
genTrafficSplitPromSample("service-1", "default"),
|
||||
genTrafficSplitPromSample("service-2", "default"),
|
||||
},
|
||||
},
|
||||
req: &pb.StatSummaryRequest{
|
||||
Selector: &pb.ResourceSelection{
|
||||
Resource: &pb.Resource{
|
||||
Namespace: "default",
|
||||
Type: pkgK8s.TrafficSplit,
|
||||
},
|
||||
},
|
||||
TimeWindow: "1m",
|
||||
},
|
||||
expectedResponse: GenStatTsResponse("authors-split", pkgK8s.TrafficSplit, []string{"default"}, true, true),
|
||||
},
|
||||
}
|
||||
testStatSummary(t, expectations)
|
||||
})
|
||||
|
||||
t.Run("Queries prometheus for TCP stats when requested", func(t *testing.T) {
|
||||
|
||||
expectations := []statSumExpected{
|
||||
|
|
@ -1309,13 +1221,6 @@ status:
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Table: &pb.StatTable_PodGroup_{
|
||||
PodGroup: &pb.StatTable_PodGroup{
|
||||
Rows: []*pb.StatTable_PodGroup_Row{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Table: &pb.StatTable_PodGroup_{
|
||||
PodGroup: &pb.StatTable_PodGroup{
|
||||
|
|
|
|||
|
|
@ -132,70 +132,6 @@ func GenStatSummaryResponse(resName, resType string, resNs []string, counts *Pod
|
|||
return resp
|
||||
}
|
||||
|
||||
// GenStatTsResponse generates a mock metrics-api StatSummaryResponse
|
||||
// object in response to a request for trafficsplit stats.
|
||||
func GenStatTsResponse(resName, resType string, resNs []string, basicStats bool, tsStats bool) *pb.StatSummaryResponse {
|
||||
leaves := map[string]string{
|
||||
"service-1": "900m",
|
||||
"service-2": "100m",
|
||||
}
|
||||
apex := "apex_name"
|
||||
|
||||
rows := []*pb.StatTable_PodGroup_Row{}
|
||||
for _, ns := range resNs {
|
||||
for name, weight := range leaves {
|
||||
statTableRow := &pb.StatTable_PodGroup_Row{
|
||||
Resource: &pb.Resource{
|
||||
Namespace: ns,
|
||||
Type: resType,
|
||||
Name: resName,
|
||||
},
|
||||
TimeWindow: "1m",
|
||||
}
|
||||
|
||||
if basicStats {
|
||||
statTableRow.Stats = &pb.BasicStats{
|
||||
SuccessCount: 123,
|
||||
FailureCount: 0,
|
||||
LatencyMsP50: 123,
|
||||
LatencyMsP95: 123,
|
||||
LatencyMsP99: 123,
|
||||
}
|
||||
}
|
||||
|
||||
if tsStats {
|
||||
statTableRow.TsStats = &pb.TrafficSplitStats{
|
||||
Apex: apex,
|
||||
Leaf: name,
|
||||
Weight: weight,
|
||||
}
|
||||
}
|
||||
rows = append(rows, statTableRow)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// sort rows before returning in order to have a consistent order for tests
|
||||
rows = sortTrafficSplitRows(rows)
|
||||
|
||||
resp := &pb.StatSummaryResponse{
|
||||
Response: &pb.StatSummaryResponse_Ok_{ // https://github.com/golang/protobuf/issues/205
|
||||
Ok: &pb.StatSummaryResponse_Ok{
|
||||
StatTables: []*pb.StatTable{
|
||||
{
|
||||
Table: &pb.StatTable_PodGroup_{
|
||||
PodGroup: &pb.StatTable_PodGroup{
|
||||
Rows: rows,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
type mockEdgeRow struct {
|
||||
resourceType string
|
||||
src string
|
||||
|
|
|
|||
|
|
@ -417,8 +417,6 @@ func (h *handler) handleAPIResourceDefinition(w http.ResponseWriter, req *http.R
|
|||
resource, err = h.k8sAPI.CoreV1().ReplicationControllers(namespace).Get(req.Context(), resourceName, options)
|
||||
case k8s.ReplicaSet:
|
||||
resource, err = h.k8sAPI.AppsV1().ReplicaSets(namespace).Get(req.Context(), resourceName, options)
|
||||
case k8s.TrafficSplit:
|
||||
resource, err = h.k8sAPI.TsClient.SplitV1alpha1().TrafficSplits(namespace).Get(req.Context(), resourceName, options)
|
||||
default:
|
||||
renderJSONError(w, errors.New("Invalid resource type: "+resourceType), http.StatusBadRequest)
|
||||
return
|
||||
|
|
|
|||
Loading…
Reference in New Issue