mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 02:43:36 +00:00
vendor files
This commit is contained in:
71
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/BUILD
generated
vendored
Normal file
71
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/BUILD
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"merge.go",
|
||||
"merge_visitor.go",
|
||||
"replace_visitor.go",
|
||||
"retain_keys_visitor.go",
|
||||
"strategic_visitor.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/apply/strategy",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//pkg/kubectl/apply:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_xtest",
|
||||
srcs = [
|
||||
"merge_map_list_test.go",
|
||||
"merge_map_test.go",
|
||||
"merge_primitive_list_test.go",
|
||||
"merge_primitive_test.go",
|
||||
"replace_map_list_test.go",
|
||||
"replace_map_test.go",
|
||||
"replace_primitive_list_test.go",
|
||||
"retain_keys_test.go",
|
||||
"suite_test.go",
|
||||
"utils_test.go",
|
||||
],
|
||||
data = [
|
||||
":swagger-spec",
|
||||
"//api/openapi-spec:swagger-spec",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/apply/strategy_test",
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//pkg/kubectl/apply:go_default_library",
|
||||
"//pkg/kubectl/apply/parse:go_default_library",
|
||||
"//pkg/kubectl/cmd/util/openapi:go_default_library",
|
||||
"//pkg/kubectl/cmd/util/openapi/testing:go_default_library",
|
||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||
"//vendor/github.com/onsi/ginkgo:go_default_library",
|
||||
"//vendor/github.com/onsi/ginkgo/config:go_default_library",
|
||||
"//vendor/github.com/onsi/ginkgo/types:go_default_library",
|
||||
"//vendor/github.com/onsi/gomega:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "swagger-spec",
|
||||
srcs = glob([
|
||||
"**/*.json",
|
||||
]),
|
||||
)
|
17
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/doc.go
generated
vendored
Normal file
17
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/doc.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
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
|
33
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge.go
generated
vendored
Normal file
33
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
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
|
||||
|
||||
import "k8s.io/kubernetes/pkg/kubectl/apply"
|
||||
|
||||
// Options controls how a merge will be executed
|
||||
type Options struct {
|
||||
// FailOnConflict when true will fail patch creation if the recorded and remote
|
||||
// have 2 fields set for the same value that cannot be merged.
|
||||
// e.g. primitive values, list values with replace strategy, and map values with do
|
||||
// strategy
|
||||
FailOnConflict bool
|
||||
}
|
||||
|
||||
// Create returns a new apply.Visitor for merging multiple objects together
|
||||
func Create(options Options) apply.Strategy {
|
||||
return createDelegatingStrategy(options)
|
||||
}
|
650
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_map_list_test.go
generated
vendored
Normal file
650
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_map_list_test.go
generated
vendored
Normal file
@ -0,0 +1,650 @@
|
||||
/*
|
||||
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/kubernetes/pkg/kubectl/apply/strategy"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
||||
tst "k8s.io/kubernetes/pkg/kubectl/cmd/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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image
|
||||
- name: item2
|
||||
image: image2
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item-keep
|
||||
image: image-keep
|
||||
- name: item-delete
|
||||
image: image-delete
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item-keep
|
||||
image: image-keep
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item-keep
|
||||
image: image-keep
|
||||
- name: item-delete
|
||||
image: image-delete
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item2
|
||||
image: image2
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item2
|
||||
image: image2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image:2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image:1
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image:2
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image:2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image:1
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image:2
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image:2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: item
|
||||
image: image:2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
protocol: TCP
|
||||
hostPort: 2020
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
protocol: TCP
|
||||
hostPort: 2020
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
protocol: TCP
|
||||
hostPort: 2020
|
||||
hostIP: "127.0.0.1"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
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() {
|
||||
})
|
||||
})
|
||||
})
|
164
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_map_test.go
generated
vendored
Normal file
164
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_map_test.go
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
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/kubernetes/pkg/kubectl/apply/strategy"
|
||||
)
|
||||
|
||||
var _ = Describe("Merging fields of type map with openapi for some fields", func() {
|
||||
Context("where a field has been deleted", func() {
|
||||
It("should delete the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
foo1:
|
||||
bar: "baz1"
|
||||
image: "1"
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
foo2: null
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
foo1:
|
||||
bar: "baz1"
|
||||
image: "1"
|
||||
foo2:
|
||||
bar: "baz2"
|
||||
image: "2"
|
||||
foo3:
|
||||
bar: "baz3"
|
||||
image: "3"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
foo3:
|
||||
bar: "baz3"
|
||||
image: "3"
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been added", func() {
|
||||
It("should add the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo1:
|
||||
bar: "baz1"
|
||||
image: "1"
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
foo1:
|
||||
bar: "baz1"
|
||||
image: "1"
|
||||
foo2:
|
||||
bar: "baz2"
|
||||
image: "2"
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
foo1:
|
||||
bar: "baz1"
|
||||
image: "1"
|
||||
foo2:
|
||||
bar: "baz2"
|
||||
image: "2"
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been updated", func() {
|
||||
It("should update the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo1:
|
||||
bar: "baz1=1"
|
||||
image: "1-1"
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
foo1:
|
||||
bar: "baz1-1"
|
||||
image: "1-1"
|
||||
foo2:
|
||||
bar: "baz2-1"
|
||||
image: "2-1"
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 2
|
||||
foo1:
|
||||
bar: "baz1-0"
|
||||
image: "1-0"
|
||||
foo2:
|
||||
bar: "baz2-0"
|
||||
image: "2-0"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
foo1:
|
||||
bar: "baz1-1"
|
||||
image: "1-1"
|
||||
foo2:
|
||||
bar: "baz2-1"
|
||||
image: "2-1"
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
189
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_primitive_list_test.go
generated
vendored
Normal file
189
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_primitive_list_test.go
generated
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
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/kubernetes/pkg/kubectl/apply/strategy"
|
||||
)
|
||||
|
||||
var _ = Describe("Merging fields of type list-of-primitive with openapi", func() {
|
||||
Context("where one of the items has been deleted", func() {
|
||||
It("should delete the deleted item", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
- "c"
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "c"
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
- "c"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "c"
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where one of the items is only on the remote", func() {
|
||||
It("should move the remote-only item to the end but keep it", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "c"
|
||||
- "b"
|
||||
- "a"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
- "c"
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where one of the items is repeated", func() {
|
||||
It("should de-duplicate the repeated items", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
- "a"
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where some items are deleted and others are on remote only", func() {
|
||||
It("should retain the correct items in the correct order", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "b"
|
||||
- "c"
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "c"
|
||||
- "a"
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "d"
|
||||
- "b"
|
||||
- "c"
|
||||
- "a"
|
||||
- "e"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
finalizers:
|
||||
- "a"
|
||||
- "c"
|
||||
- "d"
|
||||
- "e"
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
540
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_primitive_test.go
generated
vendored
Normal file
540
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_primitive_test.go
generated
vendored
Normal file
@ -0,0 +1,540 @@
|
||||
/*
|
||||
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/kubernetes/pkg/kubectl/apply/strategy"
|
||||
)
|
||||
|
||||
var _ = Describe("Merging fields of type map with openapi", func() {
|
||||
Context("where a field has been deleted", func() {
|
||||
It("should delete the field when it is the only field in the map", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# delete - recorded/remote match
|
||||
paused: true
|
||||
# delete - recorded/remote differ
|
||||
progressDeadlineSeconds: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# delete - not present in recorded
|
||||
replicas: null
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
paused: true
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should delete the field when there are other fields in the map", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# delete - recorded/remote match
|
||||
paused: true
|
||||
# delete - recorded/remote differ
|
||||
progressDeadlineSeconds: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# delete - not present in recorded
|
||||
replicas: null
|
||||
# keep
|
||||
revisionHistoryLimit: 1
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
paused: true
|
||||
progressDeadlineSeconds: 2
|
||||
revisionHistoryLimit: 1
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
revisionHistoryLimit: 1
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been added", func() {
|
||||
It("should add the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
paused: true
|
||||
progressDeadlineSeconds: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# Add this - it is missing from recorded and remote
|
||||
replicas: 3
|
||||
# Add this - it is missing from remote but matches recorded
|
||||
paused: true
|
||||
# Add this - it is missing from remote and differs from recorded
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
paused: true
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been updated", func() {
|
||||
It("should add the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
paused: true
|
||||
progressDeadlineSeconds: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# Missing from recorded
|
||||
replicas: 3
|
||||
# Matches the recorded
|
||||
paused: true
|
||||
# Differs from recorded
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 2
|
||||
paused: false
|
||||
progressDeadlineSeconds: 3
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
paused: true
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should update the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 2
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 2
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("Merging fields of type map without openapi", func() {
|
||||
Context("where a field has been deleted", func() {
|
||||
It("should delete the field when it is the only field in the map", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
# delete - recorded/remote match
|
||||
paused: true
|
||||
# delete - recorded/remote differ
|
||||
progressDeadlineSeconds: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
# delete - not present in recorded
|
||||
replicas: null
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
replicas: 3
|
||||
paused: true
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should delete the field when there are other fields in the map", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
# delete - recorded/remote match
|
||||
paused: true
|
||||
# delete - recorded/remote differ
|
||||
progressDeadlineSeconds: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
# delete - not present in recorded
|
||||
replicas: null
|
||||
# keep
|
||||
revisionHistoryLimit: 1
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
replicas: 3
|
||||
paused: true
|
||||
progressDeadlineSeconds: 2
|
||||
revisionHistoryLimit: 1
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
revisionHistoryLimit: 1
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been added", func() {
|
||||
It("should add the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
paused: true
|
||||
progressDeadlineSeconds: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
# Add this - it is missing from recorded and remote
|
||||
replicas: 3
|
||||
# Add this - it is missing from remote but matches recorded
|
||||
paused: true
|
||||
# Add this - it is missing from remote and differs from recorded
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
replicas: 3
|
||||
paused: true
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been updated", func() {
|
||||
It("should add the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
paused: true
|
||||
progressDeadlineSeconds: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
# Matches recorded
|
||||
replicas: 3
|
||||
# Matches the recorded
|
||||
paused: true
|
||||
# Differs from recorded
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
replicas: 2
|
||||
paused: false
|
||||
progressDeadlineSeconds: 3
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
replicas: 3
|
||||
paused: true
|
||||
progressDeadlineSeconds: 2
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should update the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
replicas: 2
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
replicas: 3
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
replicas: 2
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
replicas: 3
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("Merging fields of type map with openapi", func() {
|
||||
Context("where a field has been deleted", func() {
|
||||
It("should delete the field when it is the only field in the map", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# delete - recorded/remote match
|
||||
foo: true
|
||||
# delete - recorded/remote differ
|
||||
bar: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# delete - not present in recorded
|
||||
baz: null
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
baz: 3
|
||||
foo: true
|
||||
bar: 2
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should delete the field when there are other fields in the map", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# delete - recorded/remote match
|
||||
foo: true
|
||||
# delete - recorded/remote differ
|
||||
bar: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# delete - not present in recorded
|
||||
baz: null
|
||||
# keep
|
||||
biz: 1
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
bar: 3
|
||||
foo: true
|
||||
baz: 2
|
||||
biz: 1
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
biz: 1
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been added", func() {
|
||||
It("should add the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: true
|
||||
biz: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# Add this - it is missing from recorded and remote
|
||||
baz: 3
|
||||
# Add this - it is missing from remote but matches recorded
|
||||
foo: true
|
||||
# Add this - it is missing from remote and differs from recorded
|
||||
biz: 2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
baz: 3
|
||||
foo: true
|
||||
biz: 2
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been updated", func() {
|
||||
It("should add the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: true
|
||||
baz: 1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# Missing from recorded
|
||||
bar: 3
|
||||
# Matches the recorded
|
||||
foo: true
|
||||
# Differs from recorded
|
||||
baz: 2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
bar: 2
|
||||
foo: false
|
||||
baz: 3
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
bar: 3
|
||||
foo: true
|
||||
baz: 2
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
148
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_visitor.go
generated
vendored
Normal file
148
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/merge_visitor.go
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/kubectl/apply"
|
||||
)
|
||||
|
||||
func createMergeStrategy(options Options, strategic *delegatingStrategy) mergeStrategy {
|
||||
return mergeStrategy{
|
||||
strategic,
|
||||
options,
|
||||
}
|
||||
}
|
||||
|
||||
// mergeStrategy merges the values in an Element into a single Result
|
||||
type mergeStrategy struct {
|
||||
strategic *delegatingStrategy
|
||||
options Options
|
||||
}
|
||||
|
||||
// MergeList merges the lists in a ListElement into a single Result
|
||||
func (v mergeStrategy) MergeList(e apply.ListElement) (apply.Result, error) {
|
||||
// No merge logic if adding or deleting a field
|
||||
if result, done := v.doAddOrDelete(e); done {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Merge each item in the list and append it to the list
|
||||
merged := []interface{}{}
|
||||
for _, value := range e.Values {
|
||||
// Recursively merge the list element before adding the value to the list
|
||||
m, err := value.Merge(v.strategic)
|
||||
if err != nil {
|
||||
return apply.Result{}, err
|
||||
}
|
||||
|
||||
switch m.Operation {
|
||||
case apply.SET:
|
||||
// Keep the list item value
|
||||
merged = append(merged, m.MergedResult)
|
||||
case apply.DROP:
|
||||
// Drop the list item value
|
||||
default:
|
||||
panic(fmt.Errorf("Unexpected result operation type %+v", m))
|
||||
}
|
||||
}
|
||||
|
||||
if len(merged) == 0 {
|
||||
// If the list is empty, return a nil entry
|
||||
return apply.Result{Operation: apply.SET, MergedResult: nil}, nil
|
||||
}
|
||||
// Return the merged list, and tell the caller to keep it
|
||||
return apply.Result{Operation: apply.SET, MergedResult: merged}, nil
|
||||
}
|
||||
|
||||
// MergeMap merges the maps in a MapElement into a single Result
|
||||
func (v mergeStrategy) MergeMap(e apply.MapElement) (apply.Result, error) {
|
||||
// No merge logic if adding or deleting a field
|
||||
if result, done := v.doAddOrDelete(e); done {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
return v.doMergeMap(e.GetValues())
|
||||
}
|
||||
|
||||
// MergeMap merges the type instances in a TypeElement into a single Result
|
||||
func (v mergeStrategy) MergeType(e apply.TypeElement) (apply.Result, error) {
|
||||
// No merge logic if adding or deleting a field
|
||||
if result, done := v.doAddOrDelete(e); done {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
return v.doMergeMap(e.GetValues())
|
||||
}
|
||||
|
||||
// do merges a recorded, local and remote map into a new object
|
||||
func (v mergeStrategy) doMergeMap(e map[string]apply.Element) (apply.Result, error) {
|
||||
|
||||
// Merge each item in the list
|
||||
merged := map[string]interface{}{}
|
||||
for key, value := range e {
|
||||
// Recursively merge the map element before adding the value to the map
|
||||
result, err := value.Merge(v.strategic)
|
||||
if err != nil {
|
||||
return apply.Result{}, err
|
||||
}
|
||||
|
||||
switch result.Operation {
|
||||
case apply.SET:
|
||||
// Keep the map item value
|
||||
merged[key] = result.MergedResult
|
||||
case apply.DROP:
|
||||
// Drop the map item value
|
||||
default:
|
||||
panic(fmt.Errorf("Unexpected result operation type %+v", result))
|
||||
}
|
||||
}
|
||||
|
||||
// Return the merged map, and tell the caller to keep it
|
||||
if len(merged) == 0 {
|
||||
// Special case the empty map to set the field value to nil, but keep the field key
|
||||
// This is how the tests expect the structures to look when parsed from yaml
|
||||
return apply.Result{Operation: apply.SET, MergedResult: nil}, nil
|
||||
}
|
||||
return apply.Result{Operation: apply.SET, MergedResult: merged}, nil
|
||||
}
|
||||
|
||||
func (v mergeStrategy) doAddOrDelete(e apply.Element) (apply.Result, bool) {
|
||||
if apply.IsAdd(e) {
|
||||
return apply.Result{Operation: apply.SET, MergedResult: e.GetLocal()}, true
|
||||
}
|
||||
|
||||
// Delete the List
|
||||
if apply.IsDrop(e) {
|
||||
return apply.Result{Operation: apply.DROP}, true
|
||||
}
|
||||
|
||||
return apply.Result{}, false
|
||||
}
|
||||
|
||||
// MergePrimitive returns and error. Primitive elements can't be merged, only replaced.
|
||||
func (v mergeStrategy) MergePrimitive(diff apply.PrimitiveElement) (apply.Result, error) {
|
||||
return apply.Result{}, fmt.Errorf("Cannot merge primitive element %v", diff.Name)
|
||||
}
|
||||
|
||||
// MergeEmpty returns an empty result
|
||||
func (v mergeStrategy) MergeEmpty(diff apply.EmptyElement) (apply.Result, error) {
|
||||
return apply.Result{Operation: apply.SET}, nil
|
||||
}
|
||||
|
||||
var _ apply.Strategy = &mergeStrategy{}
|
73
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_map_list_test.go
generated
vendored
Normal file
73
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_map_list_test.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
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/kubernetes/pkg/kubectl/apply/strategy"
|
||||
)
|
||||
|
||||
var _ = Describe("Replacing fields of type list without openapi", func() {
|
||||
Context("where a field is has been updated", func() {
|
||||
It("should replace the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
bar:
|
||||
- name: bar1
|
||||
value: 1
|
||||
- name: bar2
|
||||
value: 2
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
bar:
|
||||
- name: bar1
|
||||
value: 1
|
||||
- name: bar2
|
||||
value: 2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
bar:
|
||||
- name: bar1
|
||||
value: 1
|
||||
- name: bar3
|
||||
value: 3
|
||||
- name: bar4
|
||||
value: 4
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
bar:
|
||||
- name: bar1
|
||||
value: 1
|
||||
- name: bar2
|
||||
value: 2
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
80
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_map_test.go
generated
vendored
Normal file
80
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_map_test.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
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/kubernetes/pkg/kubectl/apply/strategy"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
||||
tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing"
|
||||
)
|
||||
|
||||
var _ = Describe("Replacing fields of type map with openapi for some fields", func() {
|
||||
var resources openapi.Resources
|
||||
BeforeEach(func() {
|
||||
resources = tst.NewFakeResources("test_swagger.json")
|
||||
})
|
||||
|
||||
Context("where a field is has been updated", func() {
|
||||
It("should update the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: ReplicaSet
|
||||
spec:
|
||||
template:
|
||||
containers:
|
||||
- name: container1
|
||||
image: image1
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: ReplicaSet
|
||||
spec:
|
||||
template:
|
||||
containers:
|
||||
- name: container1
|
||||
image: image1
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: ReplicaSet
|
||||
spec:
|
||||
template:
|
||||
containers:
|
||||
- name: container1
|
||||
image: image1
|
||||
- name: container2
|
||||
image: image2
|
||||
- name: container3
|
||||
image: image3
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: ReplicaSet
|
||||
spec:
|
||||
template:
|
||||
containers:
|
||||
- name: container1
|
||||
image: image1
|
||||
`)
|
||||
|
||||
// Use modified swagger for ReplicaSet spec
|
||||
runWith(strategy.Create(strategy.Options{}), recorded, local, remote, expected, resources)
|
||||
})
|
||||
})
|
||||
})
|
723
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_primitive_list_test.go
generated
vendored
Normal file
723
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_primitive_list_test.go
generated
vendored
Normal file
@ -0,0 +1,723 @@
|
||||
/*
|
||||
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/kubernetes/pkg/kubectl/apply/strategy"
|
||||
)
|
||||
|
||||
var _ = Describe("Replacing fields of type list with openapi", func() {
|
||||
Context("where the field has been deleted", func() {
|
||||
It("should delete the field if present in recorded and missing from local.", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should delete the field if missing in recorded and set to null in local.", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
`)
|
||||
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where the field is has been added", func() {
|
||||
It("should add the field when missing from recorded", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should add the field when even when present in recorded", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should add the field when the parent field is missing as well", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been updated", func() {
|
||||
It("should replace the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- c
|
||||
- e
|
||||
- f
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
- z
|
||||
- "y"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- c
|
||||
- e
|
||||
- f
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should replace the field even if recorded matches", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- c
|
||||
- e
|
||||
- f
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- c
|
||||
- e
|
||||
- f
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
- z
|
||||
- "y"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- c
|
||||
- e
|
||||
- f
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
|
||||
It("should replace the field even if the only change is ordering", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- e
|
||||
- c
|
||||
- f
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- c
|
||||
- e
|
||||
- f
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- f
|
||||
- e
|
||||
- c
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- c
|
||||
- e
|
||||
- f
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("Replacing fields of type list with openapi for the type, but not the field", func() {
|
||||
Context("where a field is has been updated", func() {
|
||||
It("should replace the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- c
|
||||
- e
|
||||
- f
|
||||
otherstuff:
|
||||
- name: container1
|
||||
command:
|
||||
- e
|
||||
- f
|
||||
- g
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
- z
|
||||
- "y"
|
||||
otherstuff:
|
||||
- name: container1
|
||||
command:
|
||||
- s
|
||||
- d
|
||||
- f
|
||||
- name: container2
|
||||
command:
|
||||
- h
|
||||
- i
|
||||
- j
|
||||
- name: container3
|
||||
command:
|
||||
- k
|
||||
- l
|
||||
- m
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: container
|
||||
command:
|
||||
- c
|
||||
- e
|
||||
- f
|
||||
otherstuff:
|
||||
- name: container1
|
||||
command:
|
||||
- e
|
||||
- f
|
||||
- g
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("Replacing fields of type list without openapi", func() {
|
||||
Context("where the field has been deleted", func() {
|
||||
It("should delete the field.", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
arguments:
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
# explicitly delete this
|
||||
arguments:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
# keep this
|
||||
env:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
`)
|
||||
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
env:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where the field is has been added", func() {
|
||||
It("should add the field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
# missing from recorded - add
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
# missing from recorded - add
|
||||
arguments:
|
||||
- c
|
||||
- d
|
||||
- q
|
||||
- w
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
arguments:
|
||||
- c
|
||||
- d
|
||||
- q
|
||||
- w
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where a field is has been updated", func() {
|
||||
It("should replace field", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
env:
|
||||
- s
|
||||
- "t"
|
||||
- u
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
arguments:
|
||||
- c
|
||||
- d
|
||||
- q
|
||||
- w
|
||||
env:
|
||||
- s
|
||||
- "t"
|
||||
- u
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
spec:
|
||||
template:
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
- z
|
||||
- "y"
|
||||
arguments:
|
||||
- c
|
||||
- d
|
||||
- i
|
||||
env:
|
||||
- u
|
||||
- s
|
||||
- "t"
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Foo
|
||||
spec:
|
||||
template:
|
||||
command:
|
||||
- a
|
||||
- b
|
||||
- z
|
||||
- "y"
|
||||
arguments:
|
||||
- c
|
||||
- d
|
||||
- q
|
||||
- w
|
||||
env:
|
||||
- s
|
||||
- "t"
|
||||
- u
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
100
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_visitor.go
generated
vendored
Normal file
100
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/replace_visitor.go
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
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
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/kubectl/apply"
|
||||
)
|
||||
|
||||
// replaceVisitor creates a patch to replace a remote field value with a local field value
|
||||
type replaceStrategy struct {
|
||||
strategic *delegatingStrategy
|
||||
options Options
|
||||
}
|
||||
|
||||
func createReplaceStrategy(options Options, strategic *delegatingStrategy) replaceStrategy {
|
||||
return replaceStrategy{
|
||||
strategic,
|
||||
options,
|
||||
}
|
||||
}
|
||||
|
||||
// MergeList returns a result by merging the recorded, local and remote values
|
||||
// - replacing the remote value with the local value
|
||||
func (v replaceStrategy) MergeList(e apply.ListElement) (apply.Result, error) {
|
||||
return v.doReplace(e)
|
||||
}
|
||||
|
||||
// MergeMap returns a result by merging the recorded, local and remote values
|
||||
// - replacing the remote value with the local value
|
||||
func (v replaceStrategy) MergeMap(e apply.MapElement) (apply.Result, error) {
|
||||
return v.doReplace(e)
|
||||
}
|
||||
|
||||
// MergeType returns a result by merging the recorded, local and remote values
|
||||
// - replacing the remote value with the local value
|
||||
func (v replaceStrategy) MergeType(e apply.TypeElement) (apply.Result, error) {
|
||||
return v.doReplace(e)
|
||||
}
|
||||
|
||||
// MergePrimitive returns a result by merging the recorded, local and remote values
|
||||
// - replacing the remote value with the local value
|
||||
func (v replaceStrategy) MergePrimitive(e apply.PrimitiveElement) (apply.Result, error) {
|
||||
return v.doReplace(e)
|
||||
}
|
||||
|
||||
// MergeEmpty
|
||||
func (v replaceStrategy) MergeEmpty(e apply.EmptyElement) (apply.Result, error) {
|
||||
return apply.Result{Operation: apply.SET}, nil
|
||||
}
|
||||
|
||||
// replace returns the local value if specified, otherwise it returns the remote value
|
||||
// this works regardless of the approach
|
||||
func (v replaceStrategy) doReplace(e apply.Element) (apply.Result, error) {
|
||||
// TODO: Check for conflicts
|
||||
if result, done := v.doAddOrDelete(e); done {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
if e.HasLocal() {
|
||||
// Specified locally, set the local value
|
||||
return apply.Result{Operation: apply.SET, MergedResult: e.GetLocal()}, nil
|
||||
} else if e.HasRemote() {
|
||||
// Not specified locally, set the remote value
|
||||
return apply.Result{Operation: apply.SET, MergedResult: e.GetRemote()}, nil
|
||||
} else {
|
||||
// Only specified in the recorded, drop the field.
|
||||
return apply.Result{Operation: apply.DROP, MergedResult: e.GetRemote()}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// doAddOrDelete will check if the field should be either added or deleted. If either is true, it will
|
||||
// true the operation and true. Otherwise it will return false.
|
||||
func (v replaceStrategy) doAddOrDelete(e apply.Element) (apply.Result, bool) {
|
||||
if apply.IsAdd(e) {
|
||||
return apply.Result{Operation: apply.SET, MergedResult: e.GetLocal()}, true
|
||||
}
|
||||
|
||||
// Delete the List
|
||||
if apply.IsDrop(e) {
|
||||
return apply.Result{Operation: apply.DROP}, true
|
||||
}
|
||||
|
||||
return apply.Result{}, false
|
||||
}
|
||||
|
||||
var _ apply.Strategy = &replaceStrategy{}
|
195
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/retain_keys_test.go
generated
vendored
Normal file
195
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/retain_keys_test.go
generated
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
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/kubernetes/pkg/kubectl/apply/strategy"
|
||||
)
|
||||
|
||||
var _ = Describe("Merging fields with the retainkeys strategy", func() {
|
||||
Context("where some fields are only defined remotely", func() {
|
||||
It("should drop those fields ", func() {
|
||||
recorded := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
strategy:
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 1
|
||||
maxSurge: 1
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where some fields are defined both locally and remotely", func() {
|
||||
It("should merge those fields", func() {
|
||||
recorded := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
strategy:
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 2
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 2
|
||||
maxSurge: 1
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where the elements are in a list and some fields are only defined remotely", func() {
|
||||
It("should drop those fields ", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
volumes:
|
||||
- name: cache-volume
|
||||
emptyDir:
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
volumes:
|
||||
- name: cache-volume
|
||||
hostPath:
|
||||
path: /tmp/cache-volume
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
volumes:
|
||||
- name: cache-volume
|
||||
emptyDir:
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
|
||||
Context("where the elements are in a list", func() {
|
||||
It("the fields defined both locally and remotely should be merged", func() {
|
||||
recorded := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
`)
|
||||
local := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
volumes:
|
||||
- name: cache-volume
|
||||
hostPath:
|
||||
path: /tmp/cache-volume
|
||||
emptyDir:
|
||||
`)
|
||||
remote := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
volumes:
|
||||
- name: cache-volume
|
||||
hostPath:
|
||||
path: /tmp/cache-volume
|
||||
type: Directory
|
||||
`)
|
||||
expected := create(`
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
volumes:
|
||||
- name: cache-volume
|
||||
hostPath:
|
||||
path: /tmp/cache-volume
|
||||
type: Directory
|
||||
emptyDir:
|
||||
`)
|
||||
run(strategy.Create(strategy.Options{}), recorded, local, remote, expected)
|
||||
})
|
||||
})
|
||||
})
|
77
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/retain_keys_visitor.go
generated
vendored
Normal file
77
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/retain_keys_visitor.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/kubernetes/pkg/kubectl/apply"
|
||||
)
|
||||
|
||||
func createRetainKeysStrategy(options Options, strategic *delegatingStrategy) retainKeysStrategy {
|
||||
return retainKeysStrategy{
|
||||
&mergeStrategy{strategic, options},
|
||||
strategic,
|
||||
options,
|
||||
}
|
||||
}
|
||||
|
||||
// retainKeysStrategy merges the values in an Element into a single Result,
|
||||
// dropping any fields omitted from the local copy. (but merging values when
|
||||
// defined locally and remotely)
|
||||
type retainKeysStrategy struct {
|
||||
merge *mergeStrategy
|
||||
strategic *delegatingStrategy
|
||||
options Options
|
||||
}
|
||||
|
||||
// MergeMap merges the type instances in a TypeElement into a single Result
|
||||
// keeping only the fields defined locally, but merging their values with
|
||||
// the remote values.
|
||||
func (v retainKeysStrategy) MergeType(e apply.TypeElement) (apply.Result, error) {
|
||||
// No merge logic if adding or deleting a field
|
||||
if result, done := v.merge.doAddOrDelete(&e); done {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
elem := map[string]apply.Element{}
|
||||
for key := range e.GetLocalMap() {
|
||||
elem[key] = e.GetValues()[key]
|
||||
}
|
||||
return v.merge.doMergeMap(elem)
|
||||
}
|
||||
|
||||
// MergeMap returns an error. Only TypeElements can have retainKeys.
|
||||
func (v retainKeysStrategy) MergeMap(e apply.MapElement) (apply.Result, error) {
|
||||
return apply.Result{}, fmt.Errorf("Cannot use retainkeys with map element %v", e.Name)
|
||||
}
|
||||
|
||||
// MergeList returns an error. Only TypeElements can have retainKeys.
|
||||
func (v retainKeysStrategy) MergeList(e apply.ListElement) (apply.Result, error) {
|
||||
return apply.Result{}, fmt.Errorf("Cannot use retainkeys with list element %v", e.Name)
|
||||
}
|
||||
|
||||
// MergePrimitive returns an error. Only TypeElements can have retainKeys.
|
||||
func (v retainKeysStrategy) MergePrimitive(diff apply.PrimitiveElement) (apply.Result, error) {
|
||||
return apply.Result{}, fmt.Errorf("Cannot use retainkeys with primitive element %v", diff.Name)
|
||||
}
|
||||
|
||||
// MergeEmpty returns an empty result
|
||||
func (v retainKeysStrategy) MergeEmpty(diff apply.EmptyElement) (apply.Result, error) {
|
||||
return v.merge.MergeEmpty(diff)
|
||||
}
|
||||
|
||||
var _ apply.Strategy = &retainKeysStrategy{}
|
99
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/strategic_visitor.go
generated
vendored
Normal file
99
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/strategic_visitor.go
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
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
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/kubectl/apply"
|
||||
)
|
||||
|
||||
// delegatingStrategy delegates merging fields to other visitor implementations
|
||||
// based on the merge strategy preferred by the field.
|
||||
type delegatingStrategy struct {
|
||||
options Options
|
||||
merge mergeStrategy
|
||||
replace replaceStrategy
|
||||
retainKeys retainKeysStrategy
|
||||
}
|
||||
|
||||
// createDelegatingStrategy returns a new delegatingStrategy
|
||||
func createDelegatingStrategy(options Options) *delegatingStrategy {
|
||||
v := &delegatingStrategy{
|
||||
options: options,
|
||||
}
|
||||
v.replace = createReplaceStrategy(options, v)
|
||||
v.merge = createMergeStrategy(options, v)
|
||||
v.retainKeys = createRetainKeysStrategy(options, v)
|
||||
return v
|
||||
}
|
||||
|
||||
// MergeList delegates visiting a list based on the field patch strategy.
|
||||
// Defaults to "replace"
|
||||
func (v delegatingStrategy) MergeList(diff apply.ListElement) (apply.Result, error) {
|
||||
switch diff.GetFieldMergeType() {
|
||||
case apply.MergeStrategy:
|
||||
return v.merge.MergeList(diff)
|
||||
case apply.ReplaceStrategy:
|
||||
return v.replace.MergeList(diff)
|
||||
case apply.RetainKeysStrategy:
|
||||
return v.retainKeys.MergeList(diff)
|
||||
default:
|
||||
return v.replace.MergeList(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// MergeMap delegates visiting a map based on the field patch strategy.
|
||||
// Defaults to "merge"
|
||||
func (v delegatingStrategy) MergeMap(diff apply.MapElement) (apply.Result, error) {
|
||||
switch diff.GetFieldMergeType() {
|
||||
case apply.MergeStrategy:
|
||||
return v.merge.MergeMap(diff)
|
||||
case apply.ReplaceStrategy:
|
||||
return v.replace.MergeMap(diff)
|
||||
case apply.RetainKeysStrategy:
|
||||
return v.retainKeys.MergeMap(diff)
|
||||
default:
|
||||
return v.merge.MergeMap(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// MergeType delegates visiting a map based on the field patch strategy.
|
||||
// Defaults to "merge"
|
||||
func (v delegatingStrategy) MergeType(diff apply.TypeElement) (apply.Result, error) {
|
||||
switch diff.GetFieldMergeType() {
|
||||
case apply.MergeStrategy:
|
||||
return v.merge.MergeType(diff)
|
||||
case apply.ReplaceStrategy:
|
||||
return v.replace.MergeType(diff)
|
||||
case apply.RetainKeysStrategy:
|
||||
return v.retainKeys.MergeType(diff)
|
||||
default:
|
||||
return v.merge.MergeType(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// MergePrimitive delegates visiting a primitive to the ReplaceVisitorSingleton.
|
||||
func (v delegatingStrategy) MergePrimitive(diff apply.PrimitiveElement) (apply.Result, error) {
|
||||
// Always replace primitives
|
||||
return v.replace.MergePrimitive(diff)
|
||||
}
|
||||
|
||||
// MergeEmpty
|
||||
func (v delegatingStrategy) MergeEmpty(diff apply.EmptyElement) (apply.Result, error) {
|
||||
return v.merge.MergeEmpty(diff)
|
||||
}
|
||||
|
||||
var _ apply.Strategy = &delegatingStrategy{}
|
49
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/suite_test.go
generated
vendored
Normal file
49
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/suite_test.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
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"
|
||||
. "github.com/onsi/ginkgo/config"
|
||||
. "github.com/onsi/ginkgo/types"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOpenapi(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecsWithDefaultAndCustomReporters(t, "Openapi Suite", []Reporter{newlineReporter{}})
|
||||
}
|
||||
|
||||
// Print a newline after the default newlineReporter due to issue
|
||||
// https://github.com/jstemmer/go-junit-report/issues/31
|
||||
type newlineReporter struct{}
|
||||
|
||||
func (newlineReporter) SpecSuiteWillBegin(config GinkgoConfigType, summary *SuiteSummary) {}
|
||||
|
||||
func (newlineReporter) BeforeSuiteDidRun(setupSummary *SetupSummary) {}
|
||||
|
||||
func (newlineReporter) AfterSuiteDidRun(setupSummary *SetupSummary) {}
|
||||
|
||||
func (newlineReporter) SpecWillRun(specSummary *SpecSummary) {}
|
||||
|
||||
func (newlineReporter) SpecDidComplete(specSummary *SpecSummary) {}
|
||||
|
||||
// SpecSuiteDidEnd Prints a newline between "35 Passed | 0 Failed | 0 Pending | 0 Skipped" and "--- PASS:"
|
||||
func (newlineReporter) SpecSuiteDidEnd(summary *SuiteSummary) { fmt.Printf("\n") }
|
250
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/test_swagger.json
generated
vendored
Normal file
250
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/test_swagger.json
generated
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "Kubernetes",
|
||||
"version": "v1.9.0"
|
||||
},
|
||||
"paths": {
|
||||
},
|
||||
"definitions": {
|
||||
"io.k8s.api.core.v1.Container": {
|
||||
"description": "A single application container that you want to run within a pod.",
|
||||
"required": [
|
||||
"name",
|
||||
"image"
|
||||
],
|
||||
"properties": {
|
||||
"image": {
|
||||
"description": "Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated.",
|
||||
"type": "string"
|
||||
},
|
||||
"ports": {
|
||||
"description": "List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Cannot be updated.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.ContainerPort"
|
||||
},
|
||||
"x-kubernetes-patch-merge-key": "containerPort,protocol",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.api.core.v1.ContainerPort": {
|
||||
"description": "ContainerPort represents a network port in a single container.",
|
||||
"required": [
|
||||
"containerPort"
|
||||
],
|
||||
"properties": {
|
||||
"containerPort": {
|
||||
"description": "Number of port to expose on the pod's IP address. This must be a valid port number, 0 \u003c x \u003c 65536.",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"hostIP": {
|
||||
"description": "What host IP to bind the external port to.",
|
||||
"type": "string"
|
||||
},
|
||||
"hostPort": {
|
||||
"description": "Number of port to expose on the host. If specified, this must be a valid port number, 0 \u003c x \u003c 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this.",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"name": {
|
||||
"description": "If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services.",
|
||||
"type": "string"
|
||||
},
|
||||
"protocol": {
|
||||
"description": "Protocol for port. Must be UDP or TCP. Defaults to \"TCP\".",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.api.apps.v1beta1.Deployment": {
|
||||
"description": "DEPRECATED - This group version of Deployment is deprecated by apps/v1beta2/Deployment. See the release notes for more information. Deployment enables declarative updates for Pods and ReplicaSets.",
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"description": "Standard object metadata.",
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
|
||||
},
|
||||
"spec": {
|
||||
"description": "Specification of the desired behavior of the Deployment.",
|
||||
"$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentSpec"
|
||||
},
|
||||
},
|
||||
"x-kubernetes-group-version-kind": [
|
||||
{
|
||||
"group": "apps",
|
||||
"kind": "Deployment",
|
||||
"version": "v1beta1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"io.k8s.api.apps.v1beta1.DeploymentSpec": {
|
||||
"description": "DeploymentSpec is the specification of the desired behavior of the Deployment.",
|
||||
"required": [
|
||||
"template"
|
||||
],
|
||||
"properties": {
|
||||
"minReadySeconds": {
|
||||
"description": "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"paused": {
|
||||
"description": "Indicates that the deployment is paused.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"progressDeadlineSeconds": {
|
||||
"description": "The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Once autoRollback is implemented, the deployment controller will automatically rollback failed deployments. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s.",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1.",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"revisionHistoryLimit": {
|
||||
"description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 2.",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"template": {
|
||||
"description": "Template describes the pods that will be created.",
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec"
|
||||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": {
|
||||
"description": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"description": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"description": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"description": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
|
||||
"type": "string"
|
||||
},
|
||||
"namespace": {
|
||||
"description": "Namespace defines the space within each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.api.core.v1.PodTemplateSpec": {
|
||||
"description": "PodTemplateSpec describes the data a pod should have when created from a template",
|
||||
"properties": {
|
||||
"metadata": {
|
||||
"description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata",
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
|
||||
},
|
||||
"spec": {
|
||||
"description": "Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status",
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.PodSpec"
|
||||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.api.core.v1.PodSpec": {
|
||||
"description": "PodSpec is a description of a pod.",
|
||||
"required": [
|
||||
"containers"
|
||||
],
|
||||
"properties": {
|
||||
"containers": {
|
||||
"description": "List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.Container"
|
||||
},
|
||||
"x-kubernetes-patch-merge-key": "name",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
}
|
||||
}
|
||||
},
|
||||
"io.k8s.api.extensions.v1beta1.ReplicaSet": {
|
||||
"description": "DEPRECATED - This group version of ReplicaSet is deprecated by apps/v1beta2/ReplicaSet. See the release notes for more information. ReplicaSet represents the configuration of a ReplicaSet.",
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"description": "If the Labels of a ReplicaSet are empty, they are defaulted to be the same as the Pod(s) that the ReplicaSet manages. Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata",
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
|
||||
},
|
||||
"spec": {
|
||||
"description": "Spec defines the specification of the desired behavior of the ReplicaSet. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status",
|
||||
"$ref": "#/definitions/io.k8s.api.extensions.v1beta1.ReplicaSetSpec",
|
||||
"x-kubernetes-patch-strategy": "replace"
|
||||
|
||||
}
|
||||
},
|
||||
"x-kubernetes-group-version-kind": [
|
||||
{
|
||||
"group": "extensions",
|
||||
"kind": "ReplicaSet",
|
||||
"version": "v1beta1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"io.k8s.api.extensions.v1beta1.ReplicaSetSpec": {
|
||||
"description": "ReplicaSetSpec is the specification of a ReplicaSet.",
|
||||
"properties": {
|
||||
"minReadySeconds": {
|
||||
"description": "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Replicas is the number of desired replicas. This is a pointer to distinguish between explicit zero and unspecified. Defaults to 1. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#what-is-a-replicationcontroller",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"template": {
|
||||
"description": "Template is the object that describes the pod that will be created if insufficient replicas are detected. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template",
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"BearerToken": {
|
||||
"description": "Bearer Token authentication",
|
||||
"type": "apiKey",
|
||||
"name": "authorization",
|
||||
"in": "header"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
]
|
||||
}
|
66
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/utils_test.go
generated
vendored
Normal file
66
vendor/k8s.io/kubernetes/pkg/kubectl/apply/strategy/utils_test.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
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/gomega"
|
||||
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/kubernetes/pkg/kubectl/apply"
|
||||
"k8s.io/kubernetes/pkg/kubectl/apply/parse"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
||||
tst "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing"
|
||||
)
|
||||
|
||||
var fakeResources = tst.NewFakeResources(filepath.Join("..", "..", "..", "..", "api", "openapi-spec", "swagger.json"))
|
||||
|
||||
// run parses the openapi and runs the tests
|
||||
func run(instance apply.Strategy, recorded, local, remote, expected map[string]interface{}) {
|
||||
runWith(instance, recorded, local, remote, expected, fakeResources)
|
||||
}
|
||||
|
||||
func runWith(instance apply.Strategy, recorded, local, remote, expected map[string]interface{}, resources openapi.Resources) {
|
||||
parseFactory := parse.Factory{Resources: resources}
|
||||
|
||||
parsed, err := parseFactory.CreateElement(recorded, local, remote)
|
||||
Expect(err).Should(Not(HaveOccurred()))
|
||||
|
||||
merged, err := parsed.Merge(instance)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(merged.Operation).Should(Equal(apply.SET))
|
||||
Expect(merged.MergedResult).Should(Equal(expected), diff.ObjectDiff(merged.MergedResult, expected))
|
||||
}
|
||||
|
||||
// create parses the yaml string into a map[string]interface{}. Verifies that the string does not have
|
||||
// any tab characters.
|
||||
func create(config string) map[string]interface{} {
|
||||
result := map[string]interface{}{}
|
||||
|
||||
// The yaml parser will throw an obscure error if there are tabs in the yaml. Check for this
|
||||
Expect(strings.Contains(config, "\t")).To(
|
||||
BeFalse(), fmt.Sprintf("Yaml %s cannot contain tabs", config))
|
||||
Expect(yaml.Unmarshal([]byte(config), &result)).Should(
|
||||
Not(HaveOccurred()), fmt.Sprintf("Could not parse config:\n\n%s\n", config))
|
||||
|
||||
return result
|
||||
}
|
Reference in New Issue
Block a user