mirror of https://github.com/fluxcd/cli-utils.git
222 lines
12 KiB
Go
222 lines
12 KiB
Go
/*
|
|
Copyright 2019 The Kubernetes 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 patch_test
|
|
|
|
import (
|
|
//"encoding/json"
|
|
"fmt"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
kscheme "k8s.io/client-go/kubernetes/scheme"
|
|
"sigs.k8s.io/cli-experimental/internal/pkg/client/patch"
|
|
)
|
|
|
|
var _ = Describe("Patch", func() {
|
|
|
|
var scheme *runtime.Scheme
|
|
var dep *appsv1.Deployment
|
|
var unstructuredDeployment, modifiedDeployment *unstructured.Unstructured
|
|
var unstructuredCRD, modifiedCRD *unstructured.Unstructured
|
|
var replicaCount int32 = 2
|
|
var ns = "default"
|
|
var count uint64 = 0
|
|
var annotatedSerializedDeployment string
|
|
var serializedDeployment string
|
|
var mergePatch string
|
|
|
|
BeforeEach(func(done Done) {
|
|
dep = &appsv1.Deployment{
|
|
ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("deployment-name-%v", count), Namespace: ns},
|
|
Spec: appsv1.DeploymentSpec{
|
|
Replicas: &replicaCount,
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"foo": "bar"},
|
|
},
|
|
Template: corev1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "bar"}},
|
|
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}},
|
|
},
|
|
},
|
|
}
|
|
|
|
annotatedSerializedDeployment = `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":null,\"name\":\"deployment-name-0\",\"namespace\":\"default\"},\"spec\":{\"replicas\":2,\"selector\":{\"matchLabels\":{\"foo\":\"bar\"}},\"strategy\":{},\"template\":{\"metadata\":{\"creationTimestamp\":null,\"labels\":{\"foo\":\"bar\"}},\"spec\":{\"containers\":[{\"image\":\"nginx\",\"name\":\"nginx\",\"resources\":{}}]}}},\"status\":{}}\n"},"creationTimestamp":null,"name":"deployment-name-0","namespace":"default"},"spec":{"replicas":2,"selector":{"matchLabels":{"foo":"bar"}},"strategy":{},"template":{"metadata":{"creationTimestamp":null,"labels":{"foo":"bar"}},"spec":{"containers":[{"image":"nginx","name":"nginx","resources":{}}]}}},"status":{}}
|
|
`
|
|
serializedDeployment = `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"creationTimestamp":null,"name":"deployment-name-0","namespace":"default"},"spec":{"replicas":2,"selector":{"matchLabels":{"foo":"bar"}},"strategy":{},"template":{"metadata":{"creationTimestamp":null,"labels":{"foo":"bar"}},"spec":{"containers":[{"image":"nginx","name":"nginx","resources":{}}]}}},"status":{}}
|
|
`
|
|
mergePatch = `{"spec":{"template":{"spec":{"containers":[{"image":"nginx23","name":"nginx","resources":{}}]}}}}`
|
|
unstructuredDeployment = &unstructured.Unstructured{}
|
|
modifiedDeployment = &unstructured.Unstructured{}
|
|
unstructuredCRD = &unstructured.Unstructured{}
|
|
modifiedCRD = &unstructured.Unstructured{}
|
|
scheme = kscheme.Scheme
|
|
scheme.Convert(dep, unstructuredDeployment, nil)
|
|
scheme.Convert(dep, unstructuredCRD, nil)
|
|
dep.Spec.Template.Spec.Containers[0].Image = "nginx23"
|
|
scheme.Convert(dep, modifiedDeployment, nil)
|
|
scheme.Convert(dep, modifiedCRD, nil)
|
|
modifiedDeployment.SetGroupVersionKind(schema.GroupVersionKind{
|
|
Group: "apps",
|
|
Kind: "Deployment",
|
|
Version: "v1",
|
|
})
|
|
unstructuredDeployment.SetGroupVersionKind(schema.GroupVersionKind{
|
|
Group: "apps",
|
|
Kind: "Deployment",
|
|
Version: "v1",
|
|
})
|
|
modifiedCRD.SetGroupVersionKind(schema.GroupVersionKind{
|
|
Group: "mydomain",
|
|
Kind: "Something",
|
|
Version: "v1",
|
|
})
|
|
unstructuredCRD.SetGroupVersionKind(schema.GroupVersionKind{
|
|
Group: "mydomain",
|
|
Kind: "Something",
|
|
Version: "v1",
|
|
})
|
|
close(done)
|
|
})
|
|
|
|
AfterEach(func(done Done) {
|
|
// Cleanup
|
|
close(done)
|
|
})
|
|
|
|
Describe("Patch", func() {
|
|
Context("SerializeLastApplied", func() {
|
|
It("should get correct serialization of incoming object", func(done Done) {
|
|
By("getting the modified config for deployment")
|
|
modifiedconfig, err := patch.SerializeLastApplied(unstructuredDeployment, true)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("checking expected modified config")
|
|
Expect(string(modifiedconfig)).To(Equal(annotatedSerializedDeployment))
|
|
close(done)
|
|
})
|
|
|
|
It("should get correct non-annotated serialization of incoming object", func(done Done) {
|
|
By("getting the modified config for deployment")
|
|
modifiedconfig, err := patch.SerializeLastApplied(unstructuredDeployment, false)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("checking expected modified config")
|
|
Expect(string(modifiedconfig)).To(Equal(serializedDeployment))
|
|
close(done)
|
|
})
|
|
|
|
})
|
|
|
|
Context("SetLastApplied", func() {
|
|
It("should annotate the lastapplied of incoming object", func(done Done) {
|
|
By("set last applied")
|
|
err := patch.SetLastApplied(unstructuredDeployment)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("checking expected annotation")
|
|
lastapplied, err := patch.GetLastApplied(unstructuredDeployment)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect((string(lastapplied))).To(Equal(serializedDeployment))
|
|
close(done)
|
|
})
|
|
|
|
})
|
|
|
|
Context("GetMergePatch", func() {
|
|
It("should return the correct patch forincoming object", func(done Done) {
|
|
By("get merge patch")
|
|
p, err := patch.GetMergePatch(unstructuredDeployment, modifiedDeployment)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(p.Type).To(Equal(types.MergePatchType))
|
|
|
|
By("checking expected patch")
|
|
Expect((string(p.Data))).To(Equal(mergePatch))
|
|
close(done)
|
|
})
|
|
|
|
})
|
|
|
|
Context("GetClientSideApplyPatch", func() {
|
|
It("should return correct last-applied patch for objects without last-applied annotation", func(done Done) {
|
|
By("get merge patch without last-applied annotation and using same object")
|
|
p, err := patch.GetClientSideApplyPatch(unstructuredDeployment, unstructuredDeployment)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(p.Type).To(Equal(types.StrategicMergePatchType))
|
|
|
|
By("checking expected patch to have only metadata.annotation")
|
|
Expect((string(p.Data))).To(Equal(`{"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":null,\"name\":\"deployment-name-0\",\"namespace\":\"default\"},\"spec\":{\"replicas\":2,\"selector\":{\"matchLabels\":{\"foo\":\"bar\"}},\"strategy\":{},\"template\":{\"metadata\":{\"creationTimestamp\":null,\"labels\":{\"foo\":\"bar\"}},\"spec\":{\"containers\":[{\"image\":\"nginx\",\"name\":\"nginx\",\"resources\":{}}]}}},\"status\":{}}\n"}}}`))
|
|
|
|
By("get patch by changing deployment pod image")
|
|
p, err = patch.GetClientSideApplyPatch(unstructuredDeployment, modifiedDeployment)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(p.Type).To(Equal(types.StrategicMergePatchType))
|
|
|
|
By("checking expected patch to have metadata.annotation amd spec.template.spec changes in patch")
|
|
Expect((string(p.Data))).To(Equal(`{"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":null,\"name\":\"deployment-name-0\",\"namespace\":\"default\"},\"spec\":{\"replicas\":2,\"selector\":{\"matchLabels\":{\"foo\":\"bar\"}},\"strategy\":{},\"template\":{\"metadata\":{\"creationTimestamp\":null,\"labels\":{\"foo\":\"bar\"}},\"spec\":{\"containers\":[{\"image\":\"nginx23\",\"name\":\"nginx\",\"resources\":{}}]}}},\"status\":{}}\n"}},"spec":{"template":{"spec":{"$setElementOrder/containers":[{"name":"nginx"}],"containers":[{"image":"nginx23","name":"nginx"}]}}}}`))
|
|
close(done)
|
|
})
|
|
|
|
It("should return correct last-applied patch for objects with last-applied annotation", func(done Done) {
|
|
By("set last applied annotation")
|
|
err := patch.SetLastApplied(unstructuredDeployment)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("get merge patch with last-applied annotation and no change")
|
|
p, err := patch.GetClientSideApplyPatch(unstructuredDeployment, unstructuredDeployment)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(p.Type).To(Equal(types.StrategicMergePatchType))
|
|
|
|
By("checking expected patch to be {}")
|
|
Expect((string(p.Data))).To(Equal(`{}`))
|
|
|
|
By("get merge patch with last-applied annotation and change in deployment image")
|
|
p, err = patch.GetClientSideApplyPatch(unstructuredDeployment, modifiedDeployment)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(p.Type).To(Equal(types.StrategicMergePatchType))
|
|
|
|
By("checking expected patch to have metadata.annotation amd spec.template.spec changes in patch")
|
|
Expect((string(p.Data))).To(Equal(`{"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":null,\"name\":\"deployment-name-0\",\"namespace\":\"default\"},\"spec\":{\"replicas\":2,\"selector\":{\"matchLabels\":{\"foo\":\"bar\"}},\"strategy\":{},\"template\":{\"metadata\":{\"creationTimestamp\":null,\"labels\":{\"foo\":\"bar\"}},\"spec\":{\"containers\":[{\"image\":\"nginx23\",\"name\":\"nginx\",\"resources\":{}}]}}},\"status\":{}}\n"}},"spec":{"template":{"spec":{"$setElementOrder/containers":[{"name":"nginx"}],"containers":[{"image":"nginx23","name":"nginx"}]}}}}`))
|
|
close(done)
|
|
})
|
|
|
|
It("should return correct last-applied patch for unregistered objects", func(done Done) {
|
|
By("get merge patch with last-applied annotation and no change")
|
|
p, err := patch.GetClientSideApplyPatch(unstructuredCRD, unstructuredCRD)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(p.Type).To(Equal(types.MergePatchType))
|
|
|
|
By("checking expected patch to have metadata.annotation and .spec.template.metadata.creationTimestamp ")
|
|
Expect((string(p.Data))).To(Equal(`{"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"mydomain/v1\",\"kind\":\"Something\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":null,\"name\":\"deployment-name-0\",\"namespace\":\"default\"},\"spec\":{\"replicas\":2,\"selector\":{\"matchLabels\":{\"foo\":\"bar\"}},\"strategy\":{},\"template\":{\"metadata\":{\"creationTimestamp\":null,\"labels\":{\"foo\":\"bar\"}},\"spec\":{\"containers\":[{\"image\":\"nginx\",\"name\":\"nginx\",\"resources\":{}}]}}},\"status\":{}}\n"},"creationTimestamp":null},"spec":{"template":{"metadata":{"creationTimestamp":null}}}}`))
|
|
|
|
By("get merge patch with last-applied annotation and change in deployment image")
|
|
p, err = patch.GetClientSideApplyPatch(unstructuredCRD, modifiedCRD)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(p.Type).To(Equal(types.MergePatchType))
|
|
|
|
By("checking expected patch to have metadata.annotation amd spec.template.[metadata,spec.containers]")
|
|
Expect((string(p.Data))).To(Equal(`{"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"mydomain/v1\",\"kind\":\"Something\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":null,\"name\":\"deployment-name-0\",\"namespace\":\"default\"},\"spec\":{\"replicas\":2,\"selector\":{\"matchLabels\":{\"foo\":\"bar\"}},\"strategy\":{},\"template\":{\"metadata\":{\"creationTimestamp\":null,\"labels\":{\"foo\":\"bar\"}},\"spec\":{\"containers\":[{\"image\":\"nginx23\",\"name\":\"nginx\",\"resources\":{}}]}}},\"status\":{}}\n"},"creationTimestamp":null},"spec":{"template":{"metadata":{"creationTimestamp":null},"spec":{"containers":[{"image":"nginx23","name":"nginx","resources":{}}]}}}}`))
|
|
close(done)
|
|
})
|
|
|
|
})
|
|
})
|
|
})
|