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:
Tarun Pothulapati 2021-12-03 12:07:30 +05:30 committed by GitHub
parent c384cfd423
commit 4170b49b33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 49 additions and 3582 deletions

View File

@ -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"]

View File

@ -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

View File

@ -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",
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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",

View File

@ -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)
}

View File

@ -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))
}
}

View File

@ -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()
}

View File

@ -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)
}
})
}
}

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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"))
}

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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())

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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 ""
}

View File

@ -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))
}

View File

@ -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) {

View File

@ -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"]

View File

@ -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 {

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -3,7 +3,6 @@
"namespace": "emojivoto1",
"kind": "namespace",
"name": "emoji",
"meshed": "1/2",
"success": 1,
"rps": 2.05,
"latency_ms_p50": 123,

View File

@ -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)

View File

@ -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)

View File

@ -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{

View File

@ -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

View File

@ -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