/* Copyright 2017 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 strategy_test import ( . "github.com/onsi/ginkgo" "k8s.io/kubectl/pkg/apply/strategy" "k8s.io/kubectl/pkg/util/openapi" tst "k8s.io/kubectl/pkg/util/openapi/testing" ) var _ = Describe("Merging fields of type list-of-map with openapi", func() { Context("where one of the items has been deleted resulting in the containers being empty", func() { It("should set the containers field to null", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image - name: item2 image: image2 `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: `) run(strategy.Create(strategy.Options{}), recorded, local, remote, expected) }) }) Context("where one of the items has been deleted", func() { It("should be deleted from the result", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item-keep image: image-keep - name: item-delete image: image-delete `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item-keep image: image-keep `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item-keep image: image-keep - name: item-delete image: image-delete `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item-keep image: image-keep `) run(strategy.Create(strategy.Options{}), recorded, local, remote, expected) }) }) Context("where one of the items is only in the remote", func() { It("should leave the item", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item2 image: image2 `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item2 image: image2 `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item2 image: image2 - name: item image: image `) run(strategy.Create(strategy.Options{}), recorded, local, remote, expected) }) }) Context("where one of the items differs from the remote value and is missing from the recorded", func() { It("should update the item", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:1 `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) run(strategy.Create(strategy.Options{}), recorded, local, remote, expected) }) }) Context("where one of the items differs from the remote value but matches the recorded", func() { It("should update the item", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:1 `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) run(strategy.Create(strategy.Options{}), recorded, local, remote, expected) }) }) Context("where one of the items is missing from the remote but matches the recorded", func() { It("should add the item", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) run(strategy.Create(strategy.Options{}), recorded, local, remote, expected) }) }) Context("where one of the items is missing from the remote and missing from the recorded ", func() { It("should add the item", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: item image: image:2 `) run(strategy.Create(strategy.Options{}), recorded, local, remote, expected) }) }) Context("where the order of the resolved, local and remote lists differs", func() { It("should keep the order specified in local and append items appears only in remote", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: recorded-local image: recorded:b timeoutSeconds: 2 - name: recorded-remote image: recorded:c timeoutSeconds: 3 - name: recorded-local-remote image: recorded:d timeoutSeconds: 4 `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: local image: local:a initialDelaySeconds: 15 - name: recorded-local-remote image: local:b initialDelaySeconds: 16 - name: local-remote image: local:c initialDelaySeconds: 17 - name: recorded-local image: local:d initialDelaySeconds: 18 `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: remote image: remote:a imagePullPolicy: Always - name: recorded-remote image: remote:b imagePullPolicy: Always - name: local-remote image: remote:c imagePullPolicy: Always - name: recorded-local-remote image: remote:d imagePullPolicy: Always `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: local image: local:a initialDelaySeconds: 15 - name: recorded-local-remote image: local:b imagePullPolicy: Always initialDelaySeconds: 16 - name: local-remote image: local:c imagePullPolicy: Always initialDelaySeconds: 17 - name: recorded-local image: local:d initialDelaySeconds: 18 - name: remote image: remote:a imagePullPolicy: Always `) run(strategy.Create(strategy.Options{}), recorded, local, remote, expected) }) }) }) var _ = Describe("Merging fields of type list-of-map with openapi containing a multi-field mergekey", func() { var resources openapi.Resources BeforeEach(func() { resources = tst.NewFakeResources("test_swagger.json") }) Context("where one of the items has been deleted", func() { It("should delete the item", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 - containerPort: 8080 protocol: UDP hostPort: 2022 `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 - containerPort: 8080 protocol: UDP hostPort: 2022 hostIP: "127.0.0.1" `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 `) runWith(strategy.Create(strategy.Options{}), recorded, local, remote, expected, resources) }) }) Context("where one of the items has been updated", func() { It("should merge updates to the item", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 - containerPort: 8080 protocol: UDP hostPort: 2021 `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2023 - containerPort: 8080 protocol: UDP hostPort: 2022 `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 - containerPort: 8080 protocol: UDP hostPort: 2021 hostIP: "127.0.0.1" `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2023 - containerPort: 8080 protocol: UDP hostPort: 2022 hostIP: "127.0.0.1" `) runWith(strategy.Create(strategy.Options{}), recorded, local, remote, expected, resources) }) }) Context("where one of the items has been added", func() { It("should add the item", func() { recorded := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 `) local := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 - containerPort: 8080 protocol: UDP hostPort: 2022 `) remote := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 hostIP: "127.0.0.1" `) expected := create(` apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: container ports: - containerPort: 8080 protocol: TCP hostPort: 2020 hostIP: "127.0.0.1" - containerPort: 8080 protocol: UDP hostPort: 2022 `) runWith(strategy.Create(strategy.Options{}), recorded, local, remote, expected, resources) }) }) }) var _ = Describe("Merging fields of type list-of-map with openapi", func() { Context("containing a replace-keys sub strategy", func() { It("should apply the replace-key strategy when merging the item", func() { }) }) })