blob: 457281f45cf115abb642030b97e0e6fab36837cc [file] [log] [blame]
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package compare
import (
"strings"
"testing"
)
import (
"github.com/apache/dubbo-go-pixiu/operator/pkg/object"
)
func TestYAMLCmp(t *testing.T) {
tests := []struct {
desc string
a string
b string
want interface{}
}{
{
desc: "empty string into nil",
a: `metadata: ""`,
b: `metadata: `,
want: ``,
},
{
desc: "empty array into nil",
a: `metadata: []`,
b: `metadata: `,
want: ``,
},
{
desc: "empty map into nil",
a: `metadata: {}`,
b: `metadata: `,
want: ``,
},
{
desc: "two additional",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
namespace: dubbo-system
labels:
release: istio`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
want: `metadata:
labels:
app: <empty> -> istio-ingressgateway (ADDED)
name: <empty> -> istio-ingressgateway (ADDED)
`,
},
{
desc: "two missing",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
namespace: dubbo-system
labels:
release: istio`,
want: `metadata:
labels:
app: istio-ingressgateway -> <empty> (REMOVED)
name: istio-ingressgateway -> <empty> (REMOVED)
`,
},
{
desc: "one missing",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
release: istio`,
want: `metadata:
labels:
app: istio-ingressgateway -> <empty> (REMOVED)
`,
},
{
desc: "one additional",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
release: istio`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
want: `metadata:
labels:
app: <empty> -> istio-ingressgateway (ADDED)
`,
},
{
desc: "identical",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
want: ``,
},
{
desc: "first item changed",
a: `apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
want: `apiVersion: autoscaling/v2beta1 -> autoscaling/v2
`,
},
{
desc: "nested item changed",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-egressgateway
release: istio`,
want: `metadata:
labels:
app: istio-ingressgateway -> istio-egressgateway
`,
},
{
desc: "one map value changed, order changed",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio
spec:
maxReplicas: 5
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ingressgateway
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
labels:
app: istio-ingressgateway
release: istio
name: istio-ingressgateway
namespace: dubbo-system
spec:
maxReplicas: 5
metrics:
- resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
type: Resource
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: istio-ingressgateway`,
want: `spec:
scaleTargetRef:
name: ingressgateway -> istio-ingressgateway
`,
},
{
desc: "arrays with same items",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label1
- label2
- label3
`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label1
- label2
- label3
`,
want: ``,
},
{
desc: "arrays with different items",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label1
- label2
- label3
`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label1
- label5
- label6
`,
want: `metadata:
labels:
'[#1]': label2 -> label5
'[#2]': label3 -> label6
`,
},
{
desc: "arrays with same items, order changed",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label1
- label2
- label3
`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label2
- label3
- label1
`,
want: `metadata:
labels:
'[?->2]': <empty> -> label1 (ADDED)
'[0->?]': label1 -> <empty> (REMOVED)
`,
},
{
desc: "arrays with items",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label0
- label1
- label2
`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label4
- label5
- label2
- label3
- label1
- label0
`,
want: `metadata:
labels:
'[#0]': label0 -> label4
'[?->1]': <empty> -> label5 (ADDED)
'[?->2]': <empty> -> label2 (ADDED)
'[?->3]': <empty> -> label3 (ADDED)
'[2->5]': label2 -> label0
`,
},
{
desc: "arrays with additional items",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label1
- label2
- label3
`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label1
- label2
- label3
- label4
- label5
`,
want: `metadata:
labels:
'[?->3]': <empty> -> label4 (ADDED)
'[?->4]': <empty> -> label5 (ADDED)
`,
},
{
desc: "arrays with missing items",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label1
- label2
- label3
- label4
- label5
`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
- label1
- label2
- label3
`,
want: `metadata:
labels:
'[3->?]': label4 -> <empty> (REMOVED)
'[4->?]': label5 -> <empty> (REMOVED)
`,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
if got, want := YAMLCmp(tt.a, tt.b), tt.want; !(got == want) {
t.Errorf("%s: got:%v, want:%v", tt.desc, got, want)
}
})
}
}
func TestYAMLCmpWithIgnore(t *testing.T) {
tests := []struct {
desc string
a string
b string
i []string
want interface{}
}{
{
desc: "identical",
a: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
i: []string{"metadata.annotations.checksum/config-volume"},
want: ``,
},
{
desc: "ignore checksum",
a: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 43d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 03ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
i: []string{"metadata.annotations.checksum/config-volume"},
want: ``,
},
{
desc: "ignore missing checksum value",
a: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 43d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
i: []string{"metadata.annotations.checksum/config-volume"},
want: ``,
},
{
desc: "ignore additional checksum value",
a: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 43d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
i: []string{"metadata.annotations.checksum/config-volume"},
want: ``,
},
{
desc: "show checksum not exist",
a: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 43d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
i: []string{"metadata.annotations.checksum/config-volume"},
want: `metadata:
annotations: map[checksum/config-volume:43d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60]
-> <empty> (REMOVED)
`,
},
{
desc: "ignore by wildcard",
a: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 01d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60
name: istio-ingressgateway
namespace: dubbo-system
labels:
checksum/config-volume: 02ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 03ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
name: istio-ingressgateway
namespace: dubbo-system
labels:
checksum/config-volume: 04ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
app: istio-ingressgateway
release: istio`,
i: []string{"*.checksum/config-volume"},
want: ``,
},
{
desc: "ignore by wildcard negative",
a: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 01d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60
name: istio-ingressgateway
namespace: dubbo-system
labels:
checksum/config-volume: 02ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
app: istio-ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 03ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
name: istio-ingressgateway
namespace: dubbo-system
labels:
checksum/config-volume: 04ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
app: istio-ingressgateway
release: istio`,
i: []string{"*labels.checksum/config-volume"},
want: `metadata:
annotations:
checksum/config-volume: 01d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60
-> 03ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
`,
},
{
desc: "ignore multiple paths",
a: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 43d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 03ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
i: []string{
"metadata.annotations.checksum/config-volume",
"metadata.labels.app",
},
want: ``,
},
{
desc: "ignore multiple paths negative",
a: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 43d72e930ed33e3e01731f8bcbf31dbf02cb1c1fc53bcc09199ab45c0d031b60
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: ingressgateway
release: istio`,
b: `apiVersion: autoscaling/v2
kind: Deployment
metadata:
annotations:
checksum/config-volume: 03ba6246b2c39b48a4f8c3a92c3420a0416804d38ebe292e65cf674fb0875192
name: istio-ingressgateway
namespace: dubbo-system
labels:
app: istio-ingressgateway
release: istio`,
i: []string{
"metadata.annotations.checksum/config-volume",
},
want: `metadata:
labels:
app: ingressgateway -> istio-ingressgateway
`,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
if got, want := YAMLCmpWithIgnore(tt.a, tt.b, tt.i, ""), tt.want; !(got == want) {
t.Errorf("%s: got:%v, want:%v", tt.desc, got, want)
}
})
}
}
func TestYAMLCmpWithIgnoreTree(t *testing.T) {
tests := []struct {
desc string
a string
b string
mask string
want interface{}
}{
{
desc: "ignore masked",
a: `
ak: av
bk:
b1k: b1v
b2k: b2v
`,
b: `
ak: av
bk:
b1k: b1v-changed
b2k: b2v-changed
`,
mask: `
bk:
b1k: ignored
b2k: ignored
`,
want: ``,
},
{
desc: "ignore nested masked",
a: `
ak: av
bk:
bbk:
b1k: b1v
b2k: b2v
`,
b: `
ak: av
bk:
bbk:
b1k: b1v-changed
b2k: b2v-changed
`,
mask: `
bk:
bbk:
b1k: ignored
`,
want: `bk:
bbk:
b2k: b2v -> b2v-changed
`,
},
{
desc: "not ignore non-masked",
a: `
ak: av
bk:
bbk:
b1k: b1v
b2k: b2v
`,
b: `
ak: av
bk:
bbk:
b1k: b1v-changed
b2k: b2v
`,
mask: `
bk:
bbk:
b1k:
bbb1k: ignored
`,
want: `bk:
bbk:
b1k: b1v -> b1v-changed
`,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
if got, want := YAMLCmpWithIgnore(tt.a, tt.b, nil, tt.mask), tt.want; !(got == want) {
t.Errorf("%s: got:%v, want:%v", tt.desc, got, want)
}
})
}
}
func TestYAMLCmpWithYamlInline(t *testing.T) {
tests := []struct {
desc string
a string
b string
want interface{}
}{
{
desc: "ConfigMap data order changed",
a: `kind: ConfigMap
data:
validatingwebhookconfiguration.yaml: |-
kind: ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1beta1
metadata:
name: istio-galley
value: foo`,
b: `kind: ConfigMap
data:
validatingwebhookconfiguration.yaml: |-
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
value: foo
name: istio-galley`,
want: ``,
},
{
desc: "ConfigMap data value change",
a: `kind: ConfigMap
data:
validatingwebhookconfiguration.yaml: |-
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: istio-galley`,
b: `kind: ConfigMap
data:
validatingwebhookconfiguration.yaml: |-
kind: ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1beta2
metadata:
name: istio-galley`,
want: `data:
validatingwebhookconfiguration.yaml:
apiVersion: admissionregistration.k8s.io/v1beta1 -> admissionregistration.k8s.io/v1beta2
`,
},
{
desc: "ConfigMap data deep nested value change",
a: `apiVersion: v1
kind: ConfigMap
metadata:
name: injector-mesh
data:
mesh: |-
defaultConfig:
tracing:
zipkin:
address: zipkin.dubbo-system:9411
controlPlaneAuthPolicy: NONE
connectTimeout: 10s`,
b: `apiVersion: v1
kind: ConfigMap
metadata:
name: injector-mesh
data:
mesh: |-
defaultConfig:
connectTimeout: 10s
tracing:
zipkin:
address: zipkin.dubbo-system:9412
controlPlaneAuthPolicy: NONE`,
want: `data:
mesh:
defaultConfig:
tracing:
zipkin:
address: zipkin.dubbo-system:9411 -> zipkin.dubbo-system:9412
`,
},
{
desc: "ConfigMap data multiple changes",
a: `apiVersion: v1
kind: ConfigMap
metadata:
name: injector-mesh
namespace: dubbo-system
labels:
release: istio
data:
mesh: |-
defaultConfig:
connectTimeout: 10s
configPath: "/etc/istio/proxyv1"
serviceCluster: istio-proxy
drainDuration: 45s
parentShutdownDuration: 1m0s
proxyAdminPortA: 15000
concurrency: 2
tracing:
zipkin:
address: zipkin.dubbo-system:9411
controlPlaneAuthPolicy: NONE
discoveryAddress: istio-pilot.dubbo-system:15010`,
b: `apiVersion: v1
kind: ConfigMap
metadata:
name: injector-mesh
namespace: dubbo-system
labels:
release: istio
data:
mesh: |-
defaultConfig:
connectTimeout: 10s
configPath: "/etc/istio/proxyv2"
serviceCluster: istio-proxy
drainDuration: 45s
parentShutdownDuration: 1m0s
proxyAdminPortB: 15000
concurrency: 2
tracing:
zipkin:
address: zipkin.dubbo-system:9411
controlPlaneAuthPolicy: NONE
discoveryAddress: istio-pilot.dubbo-system:15010`,
want: `data:
mesh:
defaultConfig:
configPath: /etc/istio/proxyv1 -> /etc/istio/proxyv2
proxyAdminPortA: 15000 -> <empty> (REMOVED)
proxyAdminPortB: <empty> -> 15000 (ADDED)
`,
},
{
desc: "Not ConfigMap, identical",
a: `kind: Config
data:
validatingwebhookconfiguration.yaml: |-
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: istio-galley`,
b: `kind: Config
data:
validatingwebhookconfiguration.yaml: |-
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: istio-galley`,
want: ``,
},
{
desc: "Not ConfigMap, Order changed",
a: `kind: Config
data:
validatingwebhookconfiguration.yaml: |-
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: istio-galley`,
b: `kind: Config
data:
validatingwebhookconfiguration.yaml: |-
kind: ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1beta1
metadata:
name: istio-galley`,
want: `data:
validatingwebhookconfiguration.yaml: |-
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: istio-galley -> kind: ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1beta1
metadata:
name: istio-galley
`,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
if got, want := YAMLCmp(tt.a, tt.b), tt.want; !(got == want) {
t.Errorf("%s: got:%v, want:%v", tt.desc, got, want)
}
})
}
}
func TestManifestDiff(t *testing.T) {
testDeploymentYaml1 := `apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-citadel
namespace: dubbo-system
labels:
istio: citadel
spec:
replicas: 1
template:
metadata:
labels:
istio: citadel
spec:
containers:
- name: citadel
image: docker.io/istio/citadel:1.1.8
`
testDeploymentYaml2 := `apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-citadel
namespace: dubbo-system
labels:
istio: citadel
spec:
replicas: 1
template:
metadata:
labels:
istio: citadel
spec:
containers:
- name: citadel
image: docker.io/istio/citadel:1.2.2
`
testPodYaml1 := `apiVersion: v1
kind: Pod
metadata:
name: istio-galley-75bcd59768-hpt5t
namespace: dubbo-system
labels:
istio: galley
spec:
containers:
- name: galley
image: docker.io/istio/galley:1.1.8
ports:
- containerPort: 443
protocol: TCP
- containerPort: 15014
protocol: TCP
- containerPort: 9901
protocol: TCP
`
testServiceYaml1 := `apiVersion: v1
kind: Service
metadata:
labels:
app: pilot
name: istio-pilot
namespace: dubbo-system
spec:
type: ClusterIP
ports:
- name: grpc-xds
port: 15010
protocol: TCP
targetPort: 15010
- name: http-monitoring
port: 15014
protocol: TCP
targetPort: 15014
selector:
istio: pilot
`
manifestDiffTests := []struct {
desc string
yamlStringA string
yamlStringB string
want string
}{
{
"ManifestDiffWithIdenticalResource",
testDeploymentYaml1 + object.YAMLSeparator,
testDeploymentYaml1,
"",
},
{
"ManifestDiffWithIdenticalMultipleResources",
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
testPodYaml1 + object.YAMLSeparator + testServiceYaml1 + object.YAMLSeparator + testDeploymentYaml1,
"",
},
{
"ManifestDiffWithDifferentResource",
testDeploymentYaml1,
testDeploymentYaml2,
"Object Deployment:dubbo-system:istio-citadel has diffs",
},
{
"ManifestDiffWithDifferentMultipleResources",
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
testDeploymentYaml2 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
"Object Deployment:dubbo-system:istio-citadel has diffs",
},
{
"ManifestDiffMissingResourcesInA",
testPodYaml1 + object.YAMLSeparator + testDeploymentYaml1 + object.YAMLSeparator,
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
"Object Service:dubbo-system:istio-pilot is missing in A",
},
{
"ManifestDiffMissingResourcesInB",
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
testServiceYaml1 + object.YAMLSeparator + testPodYaml1,
"Object Deployment:dubbo-system:istio-citadel is missing in B",
},
}
for _, tt := range manifestDiffTests {
for _, v := range []bool{true, false} {
t.Run(tt.desc, func(t *testing.T) {
got, err := ManifestDiff(tt.yamlStringA, tt.yamlStringB, v)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !strings.Contains(got, tt.want) {
t.Errorf("%s:\ngot:\n%v\ndoes't contains\nwant:\n%v", tt.desc, got, tt.want)
}
})
}
}
}
func TestManifestDiffWithSelectAndIgnore(t *testing.T) {
testDeploymentYaml1 := `apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-citadel
namespace: dubbo-system
labels:
istio: citadel
spec:
replicas: 1
selector:
matchLabels:
istio: citadel
template:
metadata:
labels:
istio: citadel
spec:
containers:
- name: citadel
image: docker.io/istio/citadel:1.1.8
---
`
testDeploymentYaml2 := `apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-citadel
namespace: dubbo-system
labels:
istio: citadel
spec:
replicas: 1
selector:
matchLabels:
istio: citadel
template:
metadata:
labels:
istio: citadel
spec:
containers:
- name: citadel
image: docker.io/istio/citadel:1.2.2
---
`
testPodYaml1 := `apiVersion: v1
kind: Pod
metadata:
name: istio-galley-75bcd59768-hpt5t
namespace: dubbo-system
labels:
istio: galley
spec:
containers:
- name: galley
image: docker.io/istio/galley:1.1.8
ports:
- containerPort: 443
protocol: TCP
- containerPort: 15014
protocol: TCP
- containerPort: 9901
protocol: TCP
---
`
testServiceYaml1 := `apiVersion: v1
kind: Service
metadata:
labels:
app: pilot
name: istio-pilot
namespace: dubbo-system
spec:
type: ClusterIP
ports:
- name: grpc-xds
port: 15010
protocol: TCP
targetPort: 15010
- name: http-monitoring
port: 15014
protocol: TCP
targetPort: 15014
selector:
istio: pilot
---
`
manifestDiffWithSelectAndIgnoreTests := []struct {
desc string
yamlStringA string
yamlStringB string
selectResources string
ignoreResources string
want string
}{
{
"ManifestDiffWithSelectAndIgnoreForIdenticalResource",
testDeploymentYaml1 + object.YAMLSeparator,
testDeploymentYaml1,
"::",
"",
"",
},
{
"ManifestDiffWithSelectAndIgnoreForDifferentResourcesIgnoreSingle",
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
testDeploymentYaml1 + object.YAMLSeparator,
"Deployment:*:istio-citadel",
"Service:*:",
"",
},
{
"ManifestDiffWithSelectAndIgnoreForDifferentResourcesIgnoreMultiple",
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
testDeploymentYaml1,
"Deployment:*:istio-citadel",
"Pod::*,Service:dubbo-system:*",
"",
},
{
"ManifestDiffWithSelectAndIgnoreForDifferentResourcesSelectSingle",
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
testServiceYaml1 + object.YAMLSeparator + testDeploymentYaml1,
"Deployment::istio-citadel",
"Pod:*:*",
"",
},
{
"ManifestDiffWithSelectAndIgnoreForDifferentResourcesSelectSingle",
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
testServiceYaml1 + object.YAMLSeparator + testDeploymentYaml1,
"Deployment::istio-citadel,Service:dubbo-system:istio-pilot,Pod:*:*",
"Pod:*:*",
"",
},
{
"ManifestDiffWithSelectAndIgnoreForDifferentResourceForDefault",
testDeploymentYaml1,
testDeploymentYaml2 + object.YAMLSeparator,
"::",
"",
"Object Deployment:dubbo-system:istio-citadel has diffs",
},
{
"ManifestDiffWithSelectAndIgnoreForDifferentResourceForSingleSelectAndIgnore",
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
testDeploymentYaml2 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
"Deployment:*:*",
"Pod:*:*",
"Object Deployment:dubbo-system:istio-citadel has diffs",
},
{
"ManifestDiffWithSelectAndIgnoreForMissingResourcesInA",
testPodYaml1 + object.YAMLSeparator + testDeploymentYaml1,
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
"Pod:dubbo-system:Citadel,Service:dubbo-system:",
"Pod:*:*",
"Object Service:dubbo-system:istio-pilot is missing in A",
},
{
"ManifestDiffWithSelectAndIgnoreForMissingResourcesInB",
testDeploymentYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator + testServiceYaml1,
testServiceYaml1 + object.YAMLSeparator + testPodYaml1 + object.YAMLSeparator,
"*:dubbo-system:*",
"Pod::",
"Object Deployment:dubbo-system:istio-citadel is missing in B",
},
}
for _, tt := range manifestDiffWithSelectAndIgnoreTests {
for _, v := range []bool{true, false} {
t.Run(tt.desc, func(t *testing.T) {
got, err := ManifestDiffWithRenameSelectIgnore(tt.yamlStringA, tt.yamlStringB,
"", tt.selectResources, tt.ignoreResources, v)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !strings.Contains(got, tt.want) {
t.Errorf("%s:\ngot:\n%v\ndoes't contains\nwant:\n%v", tt.desc, got, tt.want)
}
})
}
}
}
func TestManifestDiffWithRenameSelectIgnore(t *testing.T) {
testDeploymentYaml := `apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-citadel
namespace: dubbo-system
labels:
istio: citadel
spec:
replicas: 1
selector:
matchLabels:
istio: citadel
template:
metadata:
labels:
istio: citadel
spec:
containers:
- name: citadel
image: docker.io/istio/citadel:1.1.8
---
`
testDeploymentYamlRenamed := `apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-ca
namespace: dubbo-system
labels:
istio: citadel
spec:
replicas: 1
selector:
matchLabels:
istio: citadel
template:
metadata:
labels:
istio: citadel
spec:
containers:
- name: citadel
image: docker.io/istio/citadel:1.1.8
---
`
testServiceYaml := `apiVersion: v1
kind: Service
metadata:
labels:
app: pilot
name: istio-pilot
namespace: dubbo-system
spec:
type: ClusterIP
ports:
- name: grpc-xds
port: 15010
protocol: TCP
targetPort: 15010
- name: http-monitoring
port: 15014
protocol: TCP
targetPort: 15014
selector:
istio: pilot
---
`
testServiceYamlRenamed := `apiVersion: v1
kind: Service
metadata:
labels:
app: pilot
name: istio-control
namespace: dubbo-system
spec:
type: ClusterIP
ports:
- name: grpc-xds
port: 15010
protocol: TCP
targetPort: 15010
- name: http-monitoring
port: 15014
protocol: TCP
targetPort: 15014
selector:
istio: pilot
---
`
manifestDiffWithRenameSelectIgnoreTests := []struct {
desc string
yamlStringA string
yamlStringB string
renameResources string
selectResources string
ignoreResources string
want string
}{
{
"ManifestDiffDeployWithRenamedFlagMultiResourceWildcard",
testDeploymentYaml + object.YAMLSeparator + testServiceYaml,
testDeploymentYamlRenamed + object.YAMLSeparator + testServiceYamlRenamed,
"Service:*:istio-pilot->::istio-control,Deployment::istio-citadel->::istio-ca",
"::",
"",
`
Object Deployment:dubbo-system:istio-ca has diffs:
metadata:
name: istio-citadel -> istio-ca
Object Service:dubbo-system:istio-control has diffs:
metadata:
name: istio-pilot -> istio-control
`,
},
{
"ManifestDiffDeployWithRenamedFlagMultiResource",
testDeploymentYaml + object.YAMLSeparator + testServiceYaml,
testDeploymentYamlRenamed + object.YAMLSeparator + testServiceYamlRenamed,
"Service:dubbo-system:istio-pilot->Service:dubbo-system:istio-control,Deployment:dubbo-system:istio-citadel->Deployment:dubbo-system:istio-ca",
"::",
"",
`
Object Deployment:dubbo-system:istio-ca has diffs:
metadata:
name: istio-citadel -> istio-ca
Object Service:dubbo-system:istio-control has diffs:
metadata:
name: istio-pilot -> istio-control
`,
},
{
"ManifestDiffDeployWithRenamedFlag",
testDeploymentYaml,
testDeploymentYamlRenamed,
"Deployment:dubbo-system:istio-citadel->Deployment:dubbo-system:istio-ca",
"::",
"",
`
Object Deployment:dubbo-system:istio-ca has diffs:
metadata:
name: istio-citadel -> istio-ca
`,
},
{
"ManifestDiffRenamedDeploy",
testDeploymentYaml,
testDeploymentYamlRenamed,
"",
"::",
"",
`
Object Deployment:dubbo-system:istio-ca is missing in A:
Object Deployment:dubbo-system:istio-citadel is missing in B:
`,
},
}
for _, tt := range manifestDiffWithRenameSelectIgnoreTests {
t.Run(tt.desc, func(t *testing.T) {
got, err := ManifestDiffWithRenameSelectIgnore(tt.yamlStringA, tt.yamlStringB,
tt.renameResources, tt.selectResources, tt.ignoreResources, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got != tt.want {
t.Errorf("%s:\ngot:\n%v\ndoes't equals to\nwant:\n%v", tt.desc, got, tt.want)
}
})
}
}