mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-29 01:30:51 +00:00
Compare commits
70 Commits
release-ky
...
cmd/config
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
730d1f2473 | ||
|
|
29d1a37858 | ||
|
|
37bab58095 | ||
|
|
76e72ada16 | ||
|
|
0571f13da1 | ||
|
|
b33d0f86f0 | ||
|
|
6c2c08c4df | ||
|
|
fcfe798b75 | ||
|
|
a484bd2efd | ||
|
|
c8602cf9b6 | ||
|
|
caa8fdc3cd | ||
|
|
f0ae77abd5 | ||
|
|
5d1a0346b5 | ||
|
|
2a8a17e3af | ||
|
|
f6ad78650e | ||
|
|
6c4370cd0d | ||
|
|
052deacbb2 | ||
|
|
523ab2e35f | ||
|
|
9a015ca8d5 | ||
|
|
a24cc4d305 | ||
|
|
ef76575ab6 | ||
|
|
c467f48bf2 | ||
|
|
054f56ceaf | ||
|
|
39094f2aeb | ||
|
|
49ebb3f155 | ||
|
|
fa507f782f | ||
|
|
da548f65ea | ||
|
|
8991b193c6 | ||
|
|
3c776b3435 | ||
|
|
cf61a360e0 | ||
|
|
a588f498ea | ||
|
|
573d7b7234 | ||
|
|
1d94ee86df | ||
|
|
275bf05ae2 | ||
|
|
d70f3a7958 | ||
|
|
5707962df5 | ||
|
|
63c06eeaf1 | ||
|
|
b3ce3a7882 | ||
|
|
a8b5ec2c61 | ||
|
|
d190e1c18a | ||
|
|
96ac25fff5 | ||
|
|
1d988a0fd8 | ||
|
|
6f176b1507 | ||
|
|
d2f0b1b345 | ||
|
|
c95a40933b | ||
|
|
d5a107074d | ||
|
|
d8bd6db880 | ||
|
|
d27135e3a3 | ||
|
|
282b1fa49a | ||
|
|
87b680e1c0 | ||
|
|
584eb236fd | ||
|
|
31a193f60f | ||
|
|
bf17b244e5 | ||
|
|
8338299529 | ||
|
|
7adf7eb271 | ||
|
|
06b091b175 | ||
|
|
bf03669e94 | ||
|
|
7f52c814a8 | ||
|
|
d5aac922d9 | ||
|
|
9a62d866f3 | ||
|
|
b2812838bf | ||
|
|
e59e477702 | ||
|
|
4264ad0ad4 | ||
|
|
2554cd00eb | ||
|
|
383244cd63 | ||
|
|
b9da33afd4 | ||
|
|
23e339b86c | ||
|
|
9555009df8 | ||
|
|
91a10c560c | ||
|
|
780cb19c4d |
43
.travis.yml
43
.travis.yml
@@ -1,43 +0,0 @@
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
# TODO: Speed up the slowness of the osx travis runs
|
||||
# Maybe cache brew installs?
|
||||
#
|
||||
# TODO: Uncomment when some gets the tests running on Windows.
|
||||
# - windows
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- tree
|
||||
homebrew:
|
||||
packages:
|
||||
- tree
|
||||
update: true
|
||||
|
||||
# Only clone the most recent commit.
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- "1.13"
|
||||
|
||||
go_import_path: sigs.k8s.io/kustomize
|
||||
|
||||
before_install:
|
||||
- source ./travis/consider-early-travis-exit.sh
|
||||
|
||||
# Skip the install process; let pre-commit.sh do it.
|
||||
install: true
|
||||
|
||||
script:
|
||||
- make verify-kustomize
|
||||
- ./travis/kyaml-pre-commit.sh
|
||||
- ./travis/check-go-mod.sh
|
||||
|
||||
# TBD. Suppressing for now.
|
||||
notifications:
|
||||
email: false
|
||||
11
Makefile
11
Makefile
@@ -21,7 +21,10 @@ verify-kustomize: \
|
||||
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
|
||||
.PHONY: prow-presubmit-check
|
||||
prow-presubmit-check: \
|
||||
test-unit-kustomize-all
|
||||
lint-kustomize \
|
||||
test-unit-kustomize-all \
|
||||
test-unit-cmd-all \
|
||||
test-go-mod
|
||||
|
||||
.PHONY: verify-kustomize-e2e
|
||||
verify-kustomize-e2e: test-examples-e2e-kustomize
|
||||
@@ -203,6 +206,12 @@ test-unit-kustomize-all: \
|
||||
test-unit-kustomize-cli \
|
||||
test-unit-kustomize-plugins
|
||||
|
||||
test-unit-cmd-all:
|
||||
./travis/kyaml-pre-commit.sh
|
||||
|
||||
test-go-mod:
|
||||
./travis/check-go-mod.sh
|
||||
|
||||
.PHONY:
|
||||
test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
|
||||
./hack/testExamplesAgainstKustomize.sh HEAD
|
||||
|
||||
@@ -144,8 +144,10 @@ func (p *ImageTagTransformerPlugin) findContainers(obj map[string]interface{}) e
|
||||
}
|
||||
|
||||
func isImageMatched(s, t string) bool {
|
||||
// Tag values are limited to [a-zA-Z0-9_.-].
|
||||
pattern, _ := regexp.Compile("^" + t + "(@sha256)?(:[a-zA-Z0-9_.-]*)?$")
|
||||
// Tag values are limited to [a-zA-Z0-9_.{}-].
|
||||
// Some tools like Bazel rules_k8s allow tag patterns with {} characters.
|
||||
// More info: https://github.com/bazelbuild/rules_k8s/pull/423
|
||||
pattern, _ := regexp.Compile("^" + t + "(@sha256)?(:[a-zA-Z0-9_.{}-]*)?$")
|
||||
return pattern.MatchString(s)
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ type ResMap interface {
|
||||
Append(*resource.Resource) error
|
||||
|
||||
// AppendAll appends another ResMap to self,
|
||||
// failing on any OrgId collision.
|
||||
// failing on any CurId collision.
|
||||
AppendAll(ResMap) error
|
||||
|
||||
// AbsorbAll appends, replaces or merges the contents
|
||||
|
||||
@@ -10,7 +10,5 @@ require (
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.4.0
|
||||
k8s.io/apimachinery v0.17.0
|
||||
sigs.k8s.io/kustomize/kyaml v0.0.0
|
||||
sigs.k8s.io/kustomize/kyaml v0.1.1
|
||||
)
|
||||
|
||||
replace sigs.k8s.io/kustomize/kyaml v0.0.0 => ../../kyaml
|
||||
|
||||
@@ -156,13 +156,17 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d h1:LCPbGQ34PMrwad11aMZ+dbz5SAsq/0ySjRwQ8I9Qwd8=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/apimachinery v0.17.0 h1:xRBnuie9rXcPxUkDizUsGvPf1cnlZCFu210op7J7LJo=
|
||||
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
||||
sigs.k8s.io/kustomize/kyaml v0.1.1 h1:nGUNYINljZNmlAS8uoobUv/wx/s3Pg8dNxYo+W7uYh0=
|
||||
sigs.k8s.io/kustomize/kyaml v0.1.1/go.mod h1:/NdPPfrperSCGjm55cwEro1loBVtbtVIXSb7FguK6uk=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
|
||||
@@ -38,8 +38,7 @@ func NewCreateSetterRunner(parent string) *CreateSetterRunner {
|
||||
"kind of the Resource on which to create the setter.")
|
||||
set.Flags().MarkHidden("kind")
|
||||
set.Flags().StringVar(&r.Set.SetPartialField.Type, "type", "",
|
||||
"valid OpenAPI field type -- e.g. integer,boolean,string.")
|
||||
set.Flags().MarkHidden("type")
|
||||
"OpenAPI field type for the setter -- e.g. integer,boolean,string.")
|
||||
set.Flags().BoolVar(&r.Set.SetPartialField.Partial, "partial", false,
|
||||
"create a partial setter for only part of the field value.")
|
||||
set.Flags().MarkHidden("partial")
|
||||
@@ -89,6 +88,7 @@ func (r *CreateSetterRunner) preRunE(c *cobra.Command, args []string) error {
|
||||
r.OpenAPIFile, err = ext.GetOpenAPIFile(args)
|
||||
r.CreateSetter.Description = r.Set.SetPartialField.Description
|
||||
r.CreateSetter.SetBy = r.Set.SetPartialField.SetBy
|
||||
r.CreateSetter.Type = r.Set.SetPartialField.Type
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -102,6 +102,72 @@ spec:
|
||||
image: nginx:1.7.9 # {"$ref":"#/definitions/io.k8s.cli.substitutions.image"}
|
||||
- name: sidecar
|
||||
image: sidecar:1.7.9
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "substitution and create setters 1",
|
||||
args: []string{
|
||||
"image", "something/nginx::1.7.9/nginxotherthing", "--pattern", "something/IMAGE::TAG/nginxotherthing",
|
||||
"--value", "IMAGE=image", "--value", "TAG=tag"},
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: something/nginx::1.7.9/nginxotherthing
|
||||
- name: sidecar
|
||||
image: sidecar:1.7.9
|
||||
`,
|
||||
inputOpenAPI: `
|
||||
apiVersion: v1alpha1
|
||||
kind: Example
|
||||
`,
|
||||
expectedOpenAPI: `
|
||||
apiVersion: v1alpha1
|
||||
kind: Example
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.image:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: image
|
||||
value: nginx
|
||||
io.k8s.cli.setters.tag:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: tag
|
||||
value: 1.7.9
|
||||
io.k8s.cli.substitutions.image:
|
||||
x-k8s-cli:
|
||||
substitution:
|
||||
name: image
|
||||
pattern: something/IMAGE::TAG/nginxotherthing
|
||||
values:
|
||||
- marker: IMAGE
|
||||
ref: '#/definitions/io.k8s.cli.setters.image'
|
||||
- marker: TAG
|
||||
ref: '#/definitions/io.k8s.cli.setters.tag'
|
||||
`,
|
||||
expectedResources: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: something/nginx::1.7.9/nginxotherthing # {"$ref":"#/definitions/io.k8s.cli.substitutions.image"}
|
||||
- name: sidecar
|
||||
image: sidecar:1.7.9
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -109,7 +109,6 @@ openAPI:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "4"
|
||||
setBy: me
|
||||
`,
|
||||
expectedResources: `
|
||||
apiVersion: apps/v1
|
||||
|
||||
2
functions/examples/application-cr/LICENSE_TEMPLATE
Normal file
2
functions/examples/application-cr/LICENSE_TEMPLATE
Normal file
@@ -0,0 +1,2 @@
|
||||
Copyright {{.Year}} {{.Holder}}
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
42
functions/examples/application-cr/Makefile
Normal file
42
functions/examples/application-cr/Makefile
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
all: generate license build fix vet fmt test lint tidy
|
||||
|
||||
fix:
|
||||
(cd image && go fix ./...)
|
||||
|
||||
fmt:
|
||||
(cd image && go fmt ./...)
|
||||
|
||||
generate:
|
||||
(which $(GOBIN)/mdtogo || go get sigs.k8s.io/kustomize/cmd/mdtogo)
|
||||
(cd image && GOBIN=$(GOBIN) go generate ./...)
|
||||
|
||||
license:
|
||||
(which $(GOPATH)/bin/addlicense || go get github.com/google/addlicense)
|
||||
$(GOPATH)/bin/addlicense -y 2019 -c "The Kubernetes Authors." -f LICENSE_TEMPLATE .
|
||||
|
||||
tidy:
|
||||
(cd image && go mod tidy)
|
||||
|
||||
lint:
|
||||
(which $(GOBIN)/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
|
||||
(cd image && $(GOBIN)/golangci-lint run ./...)
|
||||
|
||||
test:
|
||||
(cd image && go test -cover ./...)
|
||||
|
||||
vet:
|
||||
(cd image && go vet ./...)
|
||||
|
||||
image:
|
||||
docker build image -t gcr.io/kustomize-functions/create-application:v0.1.0
|
||||
docker push gcr.io/kustomize-functions/create-application:v0.1.0
|
||||
30
functions/examples/application-cr/README.md
Normal file
30
functions/examples/application-cr/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Append Application CR
|
||||
|
||||
This is an example of appending an Application CR to a group of resources.
|
||||
|
||||
This example is written in `go` and uses the `kyaml` libraries for parsing the
|
||||
input and writing the output. Writing in `go` is not a requirement.
|
||||
|
||||
## Function implementation
|
||||
|
||||
The function is implemented as an [image](image), and built using `make image`.
|
||||
|
||||
The template is implemented as a go program, which reads a collection of input
|
||||
Resource configuration, and looks for invalid configuration.
|
||||
|
||||
## Function invocation
|
||||
|
||||
The function is invoked by authoring a [local Resource](local-resource)
|
||||
with `metadata.annotations.[config.kubernetes.io/function]` and running:
|
||||
|
||||
kustomize config run local-resource/ --fn-path config/
|
||||
|
||||
This exits non-zero if there is an error.
|
||||
|
||||
## Running the Example
|
||||
|
||||
Run the validator with:
|
||||
|
||||
kustomize config run local-resource/ --fn-path config/
|
||||
|
||||
This will append an Application CR.
|
||||
13
functions/examples/application-cr/config/fn-config.yaml
Normal file
13
functions/examples/application-cr/config/fn-config.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
apiVersion: examples.config.kubernetes.io/v1beta1
|
||||
kind: CreateApp
|
||||
metadata:
|
||||
annotations:
|
||||
config.kubernetes.io/function: |
|
||||
container:
|
||||
image: gcr.io/kustomize-functions/create-application:v0.1.0
|
||||
spec:
|
||||
managedBy: jingfang
|
||||
name: example-app
|
||||
namespace: example-namespace
|
||||
15
functions/examples/application-cr/image/Dockerfile
Normal file
15
functions/examples/application-cr/image/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
FROM golang:1.13-stretch
|
||||
ENV CGO_ENABLED=0
|
||||
WORKDIR /go/src/
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
RUN go mod download
|
||||
COPY main.go .
|
||||
RUN go build -v -o /usr/local/bin/config-function ./
|
||||
|
||||
FROM alpine:latest
|
||||
COPY --from=0 /usr/local/bin/config-function /usr/local/bin/config-function
|
||||
CMD ["config-function"]
|
||||
BIN
functions/examples/application-cr/image/application-cr
Executable file
BIN
functions/examples/application-cr/image/application-cr
Executable file
Binary file not shown.
13
functions/examples/application-cr/image/go.mod
Normal file
13
functions/examples/application-cr/image/go.mod
Normal file
@@ -0,0 +1,13 @@
|
||||
module sigs.k8s.io/kustomize/functions/examples/application-cr
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/gogo/protobuf v1.3.1 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect
|
||||
k8s.io/apimachinery v0.17.2
|
||||
sigs.k8s.io/application v0.8.2-0.20200228023238-a3b16d81fa81
|
||||
sigs.k8s.io/kustomize/kyaml v0.1.1-0.20200227221838-a24cc4d305f4
|
||||
sigs.k8s.io/yaml v1.1.0
|
||||
)
|
||||
520
functions/examples/application-cr/image/go.sum
Normal file
520
functions/examples/application-cr/image/go.sum
Normal file
@@ -0,0 +1,520 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
|
||||
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54=
|
||||
github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
|
||||
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
|
||||
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
||||
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
||||
github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
|
||||
github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
|
||||
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
|
||||
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
|
||||
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
|
||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
|
||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||
github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o=
|
||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
|
||||
github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=
|
||||
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
|
||||
github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
|
||||
github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
|
||||
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
|
||||
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
||||
github.com/go-openapi/spec v0.19.5 h1:Xm0Ao53uqnk9QE/LlYV5DEU09UAgpliA85QoT9LzqPw=
|
||||
github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
|
||||
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
|
||||
github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
|
||||
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
|
||||
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk=
|
||||
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
|
||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
|
||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||
github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180117170059-2c42eef0765b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd h1:3x5uuvBgE6oaXJjCOvpCC1IpgJogqQ+PqGGU3ZxAgII=
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
|
||||
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48=
|
||||
k8s.io/api v0.17.0 h1:H9d/lw+VkZKEVIUc8F3wgiQ+FUXTTr21M87jXLU7yqM=
|
||||
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
|
||||
k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY=
|
||||
k8s.io/apiextensions-apiserver v0.17.0 h1:+XgcGxqaMztkbbvsORgCmHIb4uImHKvTjNyu7b8gRnA=
|
||||
k8s.io/apiextensions-apiserver v0.17.0/go.mod h1:XiIFUakZywkUl54fVXa7QTEHcqQz9HG55nHd1DCoHj8=
|
||||
k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4=
|
||||
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
|
||||
k8s.io/apimachinery v0.17.2 h1:hwDQQFbdRlpnnsR64Asdi55GyCaIP/3WQpMmbNBeWr4=
|
||||
k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
|
||||
k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg=
|
||||
k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg=
|
||||
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk=
|
||||
k8s.io/client-go v0.17.0 h1:8QOGvUGdqDMFrm9sD6IUFl256BcffynGoe80sxgTEDg=
|
||||
k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
|
||||
k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE=
|
||||
k8s.io/code-generator v0.17.0/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
|
||||
k8s.io/component-base v0.0.0-20190918160511-547f6c5d7090/go.mod h1:933PBGtQFJky3TEwYx4aEPZ4IxqhWh3R6DCmzqIn1hA=
|
||||
k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
|
||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
||||
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
|
||||
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
||||
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
||||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
|
||||
sigs.k8s.io/application v0.8.2-0.20200228023238-a3b16d81fa81 h1:UfB69/nuzg30T/EyejFxgIPHjKNbBmNL2rqOrtcV6Cs=
|
||||
sigs.k8s.io/application v0.8.2-0.20200228023238-a3b16d81fa81/go.mod h1:Mv+ht9RE/QNtITYCzRbt3XTIN6t6so6cInmiyg6wOIg=
|
||||
sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg=
|
||||
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
|
||||
sigs.k8s.io/kustomize/kyaml v0.1.1-0.20200227221838-a24cc4d305f4 h1:sAwSXsspJa7zmKAmrKlYpkdhoMjQUqA06SdBTvPL0S4=
|
||||
sigs.k8s.io/kustomize/kyaml v0.1.1-0.20200227221838-a24cc4d305f4/go.mod h1:/NdPPfrperSCGjm55cwEro1loBVtbtVIXSb7FguK6uk=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
|
||||
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
|
||||
sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH+UQM=
|
||||
sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w=
|
||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
160
functions/examples/application-cr/image/main.go
Normal file
160
functions/examples/application-cr/image/main.go
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package main implements adding an Application CR to a group of resources and
|
||||
// is run with `kustomize config run -- DIR/`.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/application/api/v1beta1"
|
||||
yaml2 "sigs.k8s.io/yaml"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
func appCR() error {
|
||||
rw := &kio.ByteReadWriter{
|
||||
Reader: os.Stdin,
|
||||
Writer: os.Stdout,
|
||||
OmitReaderAnnotations: true,
|
||||
KeepReaderAnnotations: true,
|
||||
}
|
||||
p := kio.Pipeline{
|
||||
Inputs: []kio.Reader{rw}, // read the inputs into a slice
|
||||
Filters: []kio.Filter{appCRFilter{rw: rw}},
|
||||
Outputs: []kio.Writer{rw}, // copy the inputs to the output
|
||||
}
|
||||
if err := p.Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := appCR(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// appCRFilter implements kio.Filter
|
||||
type appCRFilter struct {
|
||||
rw *kio.ByteReadWriter
|
||||
}
|
||||
|
||||
// define the input API schema as a struct
|
||||
type API struct {
|
||||
Spec struct {
|
||||
ManagedBy string `yaml:"managedBy"`
|
||||
|
||||
Name string `yaml:"name"`
|
||||
|
||||
Namespace string `yaml:"namespace"`
|
||||
|
||||
Descriptor v1beta1.Descriptor `yaml:"descriptor,omitempty"`
|
||||
} `yaml:"spec"`
|
||||
}
|
||||
|
||||
// Filter checks each resource for validity, otherwise returning an error.
|
||||
func (f appCRFilter) Filter(in []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
api := f.parseAPI()
|
||||
|
||||
groupKinds, err := getGroupKinds(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
app, err := addApplicationCR(api, groupKinds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = addApplicationLabel(api.Spec.Name, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if app != nil {
|
||||
return append(in, app), nil
|
||||
}
|
||||
return in, nil
|
||||
|
||||
}
|
||||
|
||||
// parseAPI parses the functionConfig into an API struct.
|
||||
func (f *appCRFilter) parseAPI() API {
|
||||
// parse the input function config -- TODO: simplify this
|
||||
var api API
|
||||
if err := yaml.Unmarshal([]byte(f.rw.FunctionConfig.MustString()), &api); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return api
|
||||
}
|
||||
|
||||
func getGroupKinds(in []*yaml.RNode) ([]metav1.GroupKind, error) {
|
||||
var groupKinds []metav1.GroupKind
|
||||
for _, r := range in {
|
||||
meta, err := r.GetMeta()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvk := schema.FromAPIVersionAndKind(meta.APIVersion, meta.Kind)
|
||||
|
||||
found := false
|
||||
for _, gk := range groupKinds {
|
||||
if gk.Group == gvk.Group && gk.Kind == gvk.Kind {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
groupKinds = append(groupKinds, metav1.GroupKind{
|
||||
Group: gvk.Group,
|
||||
Kind: gvk.Kind,
|
||||
})
|
||||
}
|
||||
}
|
||||
return groupKinds, nil
|
||||
}
|
||||
|
||||
func addApplicationCR(api API, groupKinds []metav1.GroupKind) (*yaml.RNode, error) {
|
||||
app := v1beta1.Application{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "app.k8s.io/v1beta1",
|
||||
Kind: "Application",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: api.Spec.Namespace,
|
||||
Name: api.Spec.Name,
|
||||
Labels: map[string]string{"app.kubernetes.io/name": api.Spec.Name},
|
||||
Annotations: map[string]string{"app.kubernetes.io/managed-by": api.Spec.ManagedBy},
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
ComponentGroupKinds: groupKinds,
|
||||
Descriptor: api.Spec.Descriptor,
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"app.kubernetes.io/name": api.Spec.Name},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := yaml2.Marshal(app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return yaml.Parse(string(data))
|
||||
}
|
||||
|
||||
func addApplicationLabel(name string, in []*yaml.RNode) error {
|
||||
for _, r := range in {
|
||||
if _, err := r.Pipe(yaml.SetLabel("app.kubernetes.io/name", name)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
251
functions/examples/application-cr/image/main_test.go
Normal file
251
functions/examples/application-cr/image/main_test.go
Normal file
@@ -0,0 +1,251 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package main implements adding an Application CR to a group of resources and
|
||||
// is run with `kustomize config run -- DIR/`.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var input = `apiVersion: config.kubernetes.io/v1alpha1
|
||||
kind: ResourceList
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map
|
||||
annotations:
|
||||
config.kubernetes.io/index: '0'
|
||||
config.kubernetes.io/path: 'example.yaml'
|
||||
data:
|
||||
altGreeting: "Good Morning!"
|
||||
enableRisky: "false"
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
annotations:
|
||||
config.kubernetes.io/index: '1'
|
||||
config.kubernetes.io/path: 'example.yaml'
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
deployment: hello
|
||||
spec:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: monopole/hello:1
|
||||
command: ["/hello", "--port=8080", "--enableRiskyFeature=$(ENABLE_RISKY)"]
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: ALT_GREETING
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: altGreeting
|
||||
- name: ENABLE_RISKY
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: enableRisky
|
||||
- kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: the-service
|
||||
annotations:
|
||||
config.kubernetes.io/index: '2'
|
||||
config.kubernetes.io/path: 'example.yaml'
|
||||
spec:
|
||||
selector:
|
||||
deployment: hello
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8666
|
||||
targetPort: 8080
|
||||
functionConfig:
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
apiVersion: examples.config.kubernetes.io/v1beta1
|
||||
kind: CreateApp
|
||||
spec:
|
||||
managedBy: jingfang
|
||||
name: example-app
|
||||
namespace: example-namespace
|
||||
descriptor:
|
||||
links:
|
||||
- description: About
|
||||
url: https://worldpress.org/
|
||||
- description: web server dashboard
|
||||
url: https://metrics/internal/worldpress-01/web-app
|
||||
`
|
||||
|
||||
var output = `apiVersion: config.kubernetes.io/v1alpha1
|
||||
kind: ResourceList
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map
|
||||
annotations:
|
||||
config.kubernetes.io/index: '0'
|
||||
config.kubernetes.io/path: 'example.yaml'
|
||||
labels:
|
||||
app.kubernetes.io/name: 'example-app'
|
||||
data:
|
||||
altGreeting: "Good Morning!"
|
||||
enableRisky: "false"
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
annotations:
|
||||
config.kubernetes.io/index: '1'
|
||||
config.kubernetes.io/path: 'example.yaml'
|
||||
labels:
|
||||
app.kubernetes.io/name: 'example-app'
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
deployment: hello
|
||||
spec:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: monopole/hello:1
|
||||
command: ["/hello", "--port=8080", "--enableRiskyFeature=$(ENABLE_RISKY)"]
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: ALT_GREETING
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: altGreeting
|
||||
- name: ENABLE_RISKY
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: enableRisky
|
||||
- kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: the-service
|
||||
annotations:
|
||||
config.kubernetes.io/index: '2'
|
||||
config.kubernetes.io/path: 'example.yaml'
|
||||
labels:
|
||||
app.kubernetes.io/name: 'example-app'
|
||||
spec:
|
||||
selector:
|
||||
deployment: hello
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8666
|
||||
targetPort: 8080
|
||||
- apiVersion: app.k8s.io/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
annotations:
|
||||
app.kubernetes.io/managed-by: jingfang
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/name: example-app
|
||||
name: example-app
|
||||
namespace: example-namespace
|
||||
spec:
|
||||
componentKinds:
|
||||
- group: ""
|
||||
kind: ConfigMap
|
||||
- group: apps
|
||||
kind: Deployment
|
||||
- group: ""
|
||||
kind: Service
|
||||
descriptor:
|
||||
links:
|
||||
- description: About
|
||||
url: https://worldpress.org/
|
||||
- description: web server dashboard
|
||||
url: https://metrics/internal/worldpress-01/web-app
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: example-app
|
||||
status: {}
|
||||
functionConfig:
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
apiVersion: examples.config.kubernetes.io/v1beta1
|
||||
kind: CreateApp
|
||||
spec:
|
||||
managedBy: jingfang
|
||||
name: example-app
|
||||
namespace: example-namespace
|
||||
descriptor:
|
||||
links:
|
||||
- description: About
|
||||
url: https://worldpress.org/
|
||||
- description: web server dashboard
|
||||
url: https://metrics/internal/worldpress-01/web-app
|
||||
`
|
||||
|
||||
func Test(t *testing.T) {
|
||||
oldStdin := os.Stdin
|
||||
oldStdout := os.Stdout
|
||||
defer func() {
|
||||
os.Stdin = oldStdin
|
||||
os.Stdout = oldStdout
|
||||
}()
|
||||
r, w, _ := os.Pipe()
|
||||
os.Stdout = w
|
||||
|
||||
outC := make(chan string)
|
||||
go func() {
|
||||
var buf bytes.Buffer
|
||||
_, err := io.Copy(&buf, r)
|
||||
if err != nil {
|
||||
outC <- ""
|
||||
}
|
||||
outC <- buf.String()
|
||||
}()
|
||||
|
||||
tmpfile, err := ioutil.TempFile("", "test-input")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(tmpfile.Name()) // noerrcheck
|
||||
if _, err := tmpfile.Write([]byte(input)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := tmpfile.Seek(0, 0); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
os.Stdin = tmpfile
|
||||
|
||||
err = appCR()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := tmpfile.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
out := <-outC
|
||||
if out != output {
|
||||
t.Fatalf("expected %s\nbut got %s\n", output, out)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map
|
||||
data:
|
||||
altGreeting: "Good Morning!"
|
||||
enableRisky: "false"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
deployment: hello
|
||||
spec:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: monopole/hello:1
|
||||
command: ["/hello", "--port=8080", "--enableRiskyFeature=$(ENABLE_RISKY)"]
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: ALT_GREETING
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: altGreeting
|
||||
- name: ENABLE_RISKY
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: enableRisky
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: the-service
|
||||
spec:
|
||||
selector:
|
||||
deployment: hello
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8666
|
||||
targetPort: 8080
|
||||
@@ -5,6 +5,7 @@ package fieldmeta
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -36,16 +37,29 @@ type PartialFieldSetter struct {
|
||||
Value string `yaml:"value" json:"value"`
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the FieldMeta has any empty Schema
|
||||
func (fm *FieldMeta) IsEmpty() bool {
|
||||
if fm == nil {
|
||||
return true
|
||||
}
|
||||
return reflect.DeepEqual(fm.Schema, spec.Schema{})
|
||||
}
|
||||
|
||||
// Read reads the FieldMeta from a node
|
||||
func (fm *FieldMeta) Read(n *yaml.RNode) error {
|
||||
if n.YNode().LineComment != "" {
|
||||
v := strings.TrimLeft(n.YNode().LineComment, "#")
|
||||
// check for metadata on head and line comments
|
||||
comments := []string{n.YNode().LineComment, n.YNode().HeadComment}
|
||||
for _, c := range comments {
|
||||
if c == "" {
|
||||
continue
|
||||
}
|
||||
c := strings.TrimLeft(c, "#")
|
||||
// if it doesn't Unmarshal that is fine, it means there is no metadata
|
||||
// other comments are valid, they just don't parse
|
||||
|
||||
// TODO: consider most sophisticated parsing techniques similar to what is used
|
||||
// TODO: consider more sophisticated parsing techniques similar to what is used
|
||||
// for go struct tags.
|
||||
if err := fm.Schema.UnmarshalJSON([]byte(v)); err != nil {
|
||||
if err := fm.Schema.UnmarshalJSON([]byte(c)); err != nil {
|
||||
// note: don't return an error if the comment isn't a fieldmeta struct
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ require (
|
||||
github.com/sergi/go-diff v1.1.0
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca
|
||||
gopkg.in/yaml.v2 v2.2.4
|
||||
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.7
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2
|
||||
)
|
||||
|
||||
10
kyaml/go.sum
10
kyaml/go.sum
@@ -39,18 +39,20 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d h1:LCPbGQ34PMrwad11aMZ+dbz5SAsq/0ySjRwQ8I9Qwd8=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
@@ -32,6 +33,14 @@ type ResourceSchema struct {
|
||||
Schema *spec.Schema
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the ResourceSchema is empty
|
||||
func (rs *ResourceSchema) IsEmpty() bool {
|
||||
if rs == nil || rs.Schema == nil {
|
||||
return true
|
||||
}
|
||||
return reflect.DeepEqual(*rs.Schema, spec.Schema{})
|
||||
}
|
||||
|
||||
// SchemaForResourceType returns the Schema for the given Resource
|
||||
// TODO(pwittrock): create a version of this function that will return a schema
|
||||
// which can be used for duck-typed Resources -- e.g. contains common fields such
|
||||
@@ -193,15 +202,15 @@ func SuppressBuiltInSchemaUse() {
|
||||
}
|
||||
|
||||
// Elements returns the Schema for the elements of an array.
|
||||
func (r *ResourceSchema) Elements() *ResourceSchema {
|
||||
func (rs *ResourceSchema) Elements() *ResourceSchema {
|
||||
// load the schema from swagger.json
|
||||
initSchema()
|
||||
|
||||
if len(r.Schema.Type) != 1 || r.Schema.Type[0] != "array" {
|
||||
if len(rs.Schema.Type) != 1 || rs.Schema.Type[0] != "array" {
|
||||
// either not an array, or array has multiple types
|
||||
return nil
|
||||
}
|
||||
s := *r.Schema.Items.Schema
|
||||
s := *rs.Schema.Items.Schema
|
||||
for s.Ref.String() != "" {
|
||||
sc, e := Resolve(&s.Ref)
|
||||
if e != nil {
|
||||
@@ -219,8 +228,8 @@ const Elements = "[]"
|
||||
// Field is called.
|
||||
// If any Field or Elements call returns nil, then Lookup returns
|
||||
// nil immediately.
|
||||
func (r *ResourceSchema) Lookup(path ...string) *ResourceSchema {
|
||||
s := r
|
||||
func (rs *ResourceSchema) Lookup(path ...string) *ResourceSchema {
|
||||
s := rs
|
||||
for _, p := range path {
|
||||
if s == nil {
|
||||
break
|
||||
@@ -235,19 +244,19 @@ func (r *ResourceSchema) Lookup(path ...string) *ResourceSchema {
|
||||
}
|
||||
|
||||
// Field returns the Schema for a field.
|
||||
func (r *ResourceSchema) Field(field string) *ResourceSchema {
|
||||
func (rs *ResourceSchema) Field(field string) *ResourceSchema {
|
||||
// load the schema from swagger.json
|
||||
initSchema()
|
||||
|
||||
// locate the Schema
|
||||
s, found := r.Schema.Properties[field]
|
||||
s, found := rs.Schema.Properties[field]
|
||||
switch {
|
||||
case found:
|
||||
// no-op, continue with s as the schema
|
||||
case r.Schema.AdditionalProperties != nil && r.Schema.AdditionalProperties.Schema != nil:
|
||||
case rs.Schema.AdditionalProperties != nil && rs.Schema.AdditionalProperties.Schema != nil:
|
||||
// map field type -- use Schema of the value
|
||||
// (the key doesn't matter, they all have the same value type)
|
||||
s = *r.Schema.AdditionalProperties.Schema
|
||||
s = *rs.Schema.AdditionalProperties.Schema
|
||||
default:
|
||||
// no Schema found from either swagger.json or line comments
|
||||
return nil
|
||||
@@ -267,14 +276,14 @@ func (r *ResourceSchema) Field(field string) *ResourceSchema {
|
||||
}
|
||||
|
||||
// PatchStrategyAndKey returns the patch strategy and merge key extensions
|
||||
func (r *ResourceSchema) PatchStrategyAndKey() (string, string) {
|
||||
ps, found := r.Schema.Extensions[kubernetesPatchStrategyExtensionKey]
|
||||
func (rs *ResourceSchema) PatchStrategyAndKey() (string, string) {
|
||||
ps, found := rs.Schema.Extensions[kubernetesPatchStrategyExtensionKey]
|
||||
if !found {
|
||||
// merge key and patch strategy must appear together
|
||||
return "", ""
|
||||
}
|
||||
|
||||
mk, found := r.Schema.Extensions[kubernetesMergeKeyExtensionKey]
|
||||
mk, found := rs.Schema.Extensions[kubernetesMergeKeyExtensionKey]
|
||||
if !found {
|
||||
// merge key and patch strategy must appear together
|
||||
return "", ""
|
||||
|
||||
@@ -104,6 +104,17 @@ type SetterDefinition struct {
|
||||
|
||||
// Count is the number of fields set by this setter.
|
||||
Count int `yaml:"count,omitempty"`
|
||||
|
||||
// Type is the type of the setter value.
|
||||
Type string `yaml:"type,omitempty"`
|
||||
|
||||
// EnumValues is a map of possible setter values to actual field values.
|
||||
// If EnumValues is specified, then the value set the by user 1) MUST
|
||||
// be present in the enumValues map as a key, and 2) the map entry value
|
||||
// MUST be used as the value to set in the configuration (rather than the key)
|
||||
// Example -- may be used for t-shirt sizing values by allowing cpu to be
|
||||
// set to small, medium or large, and then mapping these values to cpu values -- 0.5, 2, 8
|
||||
EnumValues map[string]string `yaml:"enumValues,omitempty"`
|
||||
}
|
||||
|
||||
func (sd SetterDefinition) AddToFile(path string) error {
|
||||
@@ -127,6 +138,15 @@ func (sd SetterDefinition) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
sd.Description = ""
|
||||
}
|
||||
|
||||
if sd.Type != "" {
|
||||
err = def.PipeE(yaml.FieldSetter{Name: "type", StringValue: sd.Type})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// don't write the type to the extension
|
||||
sd.Type = ""
|
||||
}
|
||||
|
||||
ext, err := def.Pipe(yaml.LookupCreate(yaml.MappingNode, K8sCliExtensionKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -30,7 +30,7 @@ func (s *Set) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
// visitScalar
|
||||
func (s *Set) visitScalar(object *yaml.RNode, p string) error {
|
||||
// get the openAPI for this field describing how to apply the setter
|
||||
ext, err := getExtFromComment(object)
|
||||
ext, sch, err := getExtFromComment(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,13 +39,13 @@ func (s *Set) visitScalar(object *yaml.RNode, p string) error {
|
||||
}
|
||||
|
||||
// perform a direct set of the field if it matches
|
||||
if s.set(object, ext) {
|
||||
if s.set(object, ext, sch) {
|
||||
s.Count++
|
||||
return nil
|
||||
}
|
||||
|
||||
// perform a substitution of the field if it matches
|
||||
sub, err := s.substitute(object, ext)
|
||||
sub, err := s.substitute(object, ext, sch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func (s *Set) visitScalar(object *yaml.RNode, p string) error {
|
||||
|
||||
// substitute updates the value of field from ext if ext contains a substitution that
|
||||
// depends on a setter whose name matches s.Name.
|
||||
func (s *Set) substitute(field *yaml.RNode, ext *cliExtension) (bool, error) {
|
||||
func (s *Set) substitute(field *yaml.RNode, ext *cliExtension, _ *spec.Schema) (bool, error) {
|
||||
nameMatch := false
|
||||
|
||||
// check partial setters to see if they contain the setter as part of a
|
||||
@@ -86,8 +86,15 @@ func (s *Set) substitute(field *yaml.RNode, ext *cliExtension) (bool, error) {
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err)
|
||||
}
|
||||
// substitute the setters current value into the substitution pattern
|
||||
p = strings.ReplaceAll(p, v.Marker, subSetter.Setter.Value)
|
||||
|
||||
if val, found := subSetter.Setter.EnumValues[subSetter.Setter.Value]; found {
|
||||
// the setter has an enum-map. we should replace the marker with the
|
||||
// enum value looked up from the map rather than the enum key
|
||||
p = strings.ReplaceAll(p, v.Marker, val)
|
||||
} else {
|
||||
// substitute the setters current value into the substitution pattern
|
||||
p = strings.ReplaceAll(p, v.Marker, subSetter.Setter.Value)
|
||||
}
|
||||
|
||||
if subSetter.Setter.Name == s.Name {
|
||||
// the substitution depends on the specified setter
|
||||
@@ -102,11 +109,15 @@ func (s *Set) substitute(field *yaml.RNode, ext *cliExtension) (bool, error) {
|
||||
// TODO(pwittrock): validate the field value
|
||||
|
||||
field.YNode().Value = p
|
||||
|
||||
// substitutions are always strings
|
||||
field.YNode().Tag = "!!str"
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// set applies the value from ext to field if its name matches s.Name
|
||||
func (s *Set) set(field *yaml.RNode, ext *cliExtension) bool {
|
||||
func (s *Set) set(field *yaml.RNode, ext *cliExtension, sch *spec.Schema) bool {
|
||||
// check full setter
|
||||
if ext.Setter == nil || ext.Setter.Name != s.Name {
|
||||
return false
|
||||
@@ -114,8 +125,18 @@ func (s *Set) set(field *yaml.RNode, ext *cliExtension) bool {
|
||||
|
||||
// TODO(pwittrock): validate the field value
|
||||
|
||||
if val, found := ext.Setter.EnumValues[ext.Setter.Value]; found {
|
||||
// the setter has an enum-map. we should replace the marker with the
|
||||
// enum value looked up from the map rather than the enum key
|
||||
field.YNode().Value = val
|
||||
return true
|
||||
}
|
||||
|
||||
// this has a full setter, set its value
|
||||
field.YNode().Value = ext.Setter.Value
|
||||
|
||||
// format the node so it is quoted if it is a string
|
||||
yaml.FormatNonStringStyle(field.YNode(), *sch)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -146,14 +167,50 @@ func (s SetOpenAPI) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
if def == nil {
|
||||
return nil, errors.Errorf("no setter %s found", s.Name)
|
||||
}
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "value", StringValue: s.Value}); err != nil {
|
||||
|
||||
// if the setter contains an enumValues map, then ensure the set value appears
|
||||
// as a key in the map
|
||||
if values, err := def.Pipe(yaml.Lookup("enumValues")); err != nil {
|
||||
// error looking up the enumValues
|
||||
return nil, err
|
||||
} else if values != nil {
|
||||
// contains enumValues map -- validate the set value against the map entries
|
||||
|
||||
// get the enumValues keys
|
||||
fields, err := values.Fields()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// search for the user provided value in the set of allowed values
|
||||
var match bool
|
||||
for i := range fields {
|
||||
if fields[i] == s.Value {
|
||||
// found a match, we are good
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
// no match found -- provide an informative error to the user
|
||||
return nil, errors.Errorf("%s does not match the possible values for %s: [%s]",
|
||||
s.Value, s.Name, strings.Join(fields, ","))
|
||||
}
|
||||
}
|
||||
|
||||
v := yaml.NewScalarRNode(s.Value)
|
||||
// values are always represented as strings the OpenAPI
|
||||
// since the are unmarshalled into strings. Use double quote style to
|
||||
// ensure this consistently.
|
||||
v.YNode().Tag = "!!str"
|
||||
v.YNode().Style = yaml.DoubleQuotedStyle
|
||||
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "value", Value: v}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.SetBy != "" {
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "setBy", StringValue: s.SetBy}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "setBy", StringValue: s.SetBy}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.Description != "" {
|
||||
|
||||
@@ -15,11 +15,12 @@ import (
|
||||
|
||||
func TestSet_Filter(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
setter string
|
||||
openapi string
|
||||
input string
|
||||
expected string
|
||||
name string
|
||||
description string
|
||||
setter string
|
||||
openapi string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "set-replicas",
|
||||
@@ -58,6 +59,184 @@ metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 4 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-foo-type",
|
||||
description: "if a type is specified for a setter, ensure the field is properly quoted",
|
||||
setter: "foo",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.foo:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: foo
|
||||
value: "4"
|
||||
type: string
|
||||
`,
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.foo"}
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: "4" # {"$ref": "#/definitions/io.k8s.cli.setters.foo"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-foo-type-wrong",
|
||||
description: "if a type is specified for a setter, for the field to the type",
|
||||
setter: "foo",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.foo:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: foo
|
||||
value: "4"
|
||||
type: boolean
|
||||
`,
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.foo"}
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: !!bool 4 # {"$ref": "#/definitions/io.k8s.cli.setters.foo"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-foo-no-type",
|
||||
description: "if a type is not specified for a setter, keep the existing quoting",
|
||||
setter: "foo",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.foo:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: foo
|
||||
value: "4"
|
||||
`,
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.foo"}
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: 4 # {"$ref": "#/definitions/io.k8s.cli.setters.foo"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-replicas-enum",
|
||||
setter: "replicas",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.no-match-1':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-1
|
||||
value: "1"
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "medium"
|
||||
enumValues:
|
||||
small: "1"
|
||||
medium: "5"
|
||||
large: "50"
|
||||
io.k8s.cli.setters.no-match-2':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-2
|
||||
value: "2"
|
||||
`,
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 1 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 5 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-replicas-enum-large",
|
||||
setter: "replicas",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.no-match-1':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-1
|
||||
value: "1"
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "large"
|
||||
enumValues:
|
||||
small: "1"
|
||||
medium: "5"
|
||||
large: "50"
|
||||
io.k8s.cli.setters.no-match-2':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-2
|
||||
value: "2"
|
||||
`,
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 1 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 50 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -155,6 +334,61 @@ spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "substitute-image-name-enum",
|
||||
setter: "image-tag",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.image-name:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: image-name
|
||||
value: "helloworld"
|
||||
enumValues:
|
||||
nginx: gcr.io/nginx
|
||||
helloworld: us.gcr.io/helloworld
|
||||
io.k8s.cli.setters.image-tag:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: image-tag
|
||||
value: "1.8.1"
|
||||
io.k8s.cli.substitutions.image:
|
||||
x-k8s-cli:
|
||||
substitution:
|
||||
name: image
|
||||
pattern: IMAGE_NAME:IMAGE_TAG
|
||||
values:
|
||||
- marker: "IMAGE_NAME"
|
||||
ref: "#/definitions/io.k8s.cli.setters.image-name"
|
||||
- marker: "IMAGE_TAG"
|
||||
ref: "#/definitions/io.k8s.cli.setters.image-tag"
|
||||
`,
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: us.gcr.io/helloworld:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -491,6 +725,29 @@ openAPI:
|
||||
setter:
|
||||
name: no-match-2
|
||||
value: "2"
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-annotation-quoted",
|
||||
setter: "replicas",
|
||||
value: "3",
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: 4
|
||||
`,
|
||||
expected: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "3"
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -583,6 +840,137 @@ openAPI:
|
||||
value: "2"
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-replicas-set-by-empty",
|
||||
setter: "replicas",
|
||||
value: "3",
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.no-match-1':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-1
|
||||
value: "1"
|
||||
setBy: "package-default"
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "4"
|
||||
setBy: "package-default"
|
||||
io.k8s.cli.setters.no-match-2':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-2
|
||||
value: "2"
|
||||
setBy: "package-default"
|
||||
`,
|
||||
expected: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.no-match-1':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-1
|
||||
value: "1"
|
||||
setBy: "package-default"
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "3"
|
||||
io.k8s.cli.setters.no-match-2':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-2
|
||||
value: "2"
|
||||
setBy: "package-default"
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-replicas-with-enum",
|
||||
setter: "replicas",
|
||||
value: "baz",
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.no-match-1':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-1
|
||||
value: "1"
|
||||
setBy: "package-default"
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "foo"
|
||||
enumValues:
|
||||
foo: bar
|
||||
baz: biz
|
||||
io.k8s.cli.setters.no-match-2':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-2
|
||||
value: "2"
|
||||
setBy: "package-default"
|
||||
`,
|
||||
expected: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.no-match-1':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-1
|
||||
value: "1"
|
||||
setBy: "package-default"
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "baz"
|
||||
enumValues:
|
||||
foo: bar
|
||||
baz: biz
|
||||
io.k8s.cli.setters.no-match-2':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-2
|
||||
value: "2"
|
||||
setBy: "package-default"
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-replicas-fail",
|
||||
setter: "replicas",
|
||||
value: "hello",
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.no-match-1':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-1
|
||||
value: "1"
|
||||
setBy: "package-default"
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "foo"
|
||||
enumValues:
|
||||
foo: bar
|
||||
baz: biz
|
||||
io.k8s.cli.setters.no-match-2':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: no-match-2
|
||||
value: "2"
|
||||
setBy: "package-default"
|
||||
`,
|
||||
err: "hello does not match the possible values for replicas: [foo,baz]",
|
||||
},
|
||||
{
|
||||
name: "error",
|
||||
setter: "replicas",
|
||||
|
||||
@@ -19,6 +19,8 @@ type SetterCreator struct {
|
||||
|
||||
SetBy string
|
||||
|
||||
Type string
|
||||
|
||||
// FieldName if set will add the OpenAPI reference to fields with this name or path
|
||||
// FieldName may be the full name of the field, full path to the field, or the path suffix.
|
||||
// e.g. all of the following would match spec.template.spec.containers.image --
|
||||
@@ -35,7 +37,9 @@ type SetterCreator struct {
|
||||
func (c SetterCreator) Create(openAPIPath, resourcesPath string) error {
|
||||
// Update the OpenAPI definitions to hace the setter
|
||||
sd := setters2.SetterDefinition{
|
||||
Name: c.Name, Value: c.FieldValue, Description: c.Description, SetBy: c.SetBy}
|
||||
Name: c.Name, Value: c.FieldValue, Description: c.Description, SetBy: c.SetBy,
|
||||
Type: c.Type,
|
||||
}
|
||||
if err := sd.AddToFile(openAPIPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
package settersutil
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters2"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
// SubstitutionCreator creates or updates a substitution in the OpenAPI definitions, and
|
||||
@@ -40,6 +44,12 @@ func (c SubstitutionCreator) Create(openAPIPath, resourcesPath string) error {
|
||||
Values: c.Values,
|
||||
Pattern: c.Pattern,
|
||||
}
|
||||
|
||||
err := c.CreateSettersForSubstitution(openAPIPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.AddToFile(openAPIPath); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -62,3 +72,187 @@ func (c SubstitutionCreator) Create(openAPIPath, resourcesPath string) error {
|
||||
Outputs: []kio.Writer{inout},
|
||||
}.Execute()
|
||||
}
|
||||
|
||||
// CreateSettersForSubstitution creates the setters for all the references in the substitution
|
||||
// values if they don't already exist in openAPIPath file.
|
||||
func (c SubstitutionCreator) CreateSettersForSubstitution(openAPIPath string) error {
|
||||
y, err := yaml.ReadFile(openAPIPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m, err := c.GetValuesForMarkers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// for each ref in values, check if the setter already exists, if not create them
|
||||
for _, value := range c.Values {
|
||||
obj, err := y.Pipe(yaml.Lookup(
|
||||
// get the setter key from ref. Ex: from #/definitions/io.k8s.cli.setters.image_setter
|
||||
// extract io.k8s.cli.setters.image_setter
|
||||
"openAPI", "definitions", strings.TrimPrefix(value.Ref, "#/definitions/")))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if obj == nil {
|
||||
sd := setters2.SetterDefinition{
|
||||
// get the setter name from ref. Ex: from #/definitions/io.k8s.cli.setters.image_setter
|
||||
// extract image_setter
|
||||
Name: strings.TrimPrefix(value.Ref, "#/definitions/io.k8s.cli.setters."),
|
||||
Value: m[value.Marker],
|
||||
}
|
||||
err := sd.AddToFile(openAPIPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetValuesForMarkers parses the pattern and field value to derive values for the
|
||||
// markers in the pattern string. Returns error if the marker values can't be derived
|
||||
func (c SubstitutionCreator) GetValuesForMarkers() (map[string]string, error) {
|
||||
m := make(map[string]string)
|
||||
indices, err := c.GetStartIndices()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fv := c.FieldValue
|
||||
pattern := c.Pattern
|
||||
fvInd := 0
|
||||
patternInd := 0
|
||||
// iterate fv, pattern with indices fvInd, patternInd respectively and when patternInd hits the index of a marker,
|
||||
// freeze patternInd and iterate fvInd and capture string till we find the substring just after current marker
|
||||
// and before next marker
|
||||
|
||||
// Ex: fv = "something/ubuntu:0.1.0", pattern = "something/IMAGE:VERSION", till patternInd reaches 10
|
||||
// just proceed fvInd and patternInd and check if fv[fvInd]==pattern[patternInd] when patternInd is 10,
|
||||
// freeze patternInd and move fvInd till it sees substring ':' which derives IMAGE = ubuntu and so on.
|
||||
for fvInd < len(fv) && patternInd < len(pattern) {
|
||||
// if we hit marker index, extract its corresponding value
|
||||
if marker, ok := indices[patternInd]; ok {
|
||||
// increment the patternInd to end of marker. This helps us to extract the substring before next marker.
|
||||
patternInd += len(marker)
|
||||
var value string
|
||||
if value, fvInd, err = c.extractValueForMarker(fvInd, fv, patternInd, indices); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// if marker is repeated in the pattern, make sure that the corresponding values
|
||||
// are same and throw error if not.
|
||||
if prevValue, ok := m[marker]; ok && prevValue != value {
|
||||
return nil, errors.Errorf(
|
||||
"marker %s is found to have different values %s and %s", marker, prevValue, value)
|
||||
}
|
||||
m[marker] = value
|
||||
} else {
|
||||
// Ex: fv = "samething/ubuntu:0.1.0" pattern = "something/IMAGE:VERSION". Error out at 'a' in fv.
|
||||
if fv[fvInd] != pattern[patternInd] {
|
||||
return nil, errors.Errorf(
|
||||
"unable to derive values for markers, " +
|
||||
"create setters for all markers and then try again")
|
||||
}
|
||||
fvInd++
|
||||
patternInd++
|
||||
}
|
||||
}
|
||||
// check if both strings are completely visited or throw error
|
||||
if fvInd < len(fv) || patternInd < len(pattern) {
|
||||
return nil, errors.Errorf(
|
||||
"unable to derive values for markers, " +
|
||||
"create setters for all markers and then try again")
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// GetStartIndices returns the start indices of all the markers in the pattern
|
||||
func (c SubstitutionCreator) GetStartIndices() (map[int]string, error) {
|
||||
indices := make(map[int]string)
|
||||
for _, value := range c.Values {
|
||||
found := false
|
||||
for i := range c.Pattern {
|
||||
if strings.HasPrefix(c.Pattern[i:], value.Marker) {
|
||||
indices[i] = value.Marker
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, errors.Errorf("unable to find marker " + value.Marker + " in the pattern")
|
||||
}
|
||||
}
|
||||
if err := validateMarkers(indices); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return indices, nil
|
||||
}
|
||||
|
||||
// validateMarkers takes the indices map, checks if any of 2 markers not have delimiters,
|
||||
// checks if any marker is substring of other and returns error
|
||||
func validateMarkers(indices map[int]string) error {
|
||||
for k1, v1 := range indices {
|
||||
for k2, v2 := range indices {
|
||||
if k1 != k2 && k1+len(v1) == k2 {
|
||||
return errors.Errorf(
|
||||
"markers %s and %s are found to have no delimiters between them,"+
|
||||
" pre-create setters and try again", v1, v2)
|
||||
}
|
||||
if v1 != v2 && strings.Contains(v1, v2) {
|
||||
return errors.Errorf(
|
||||
"markers %s is substring of %s,"+
|
||||
" no marker should be substring of other", v2, v1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// extractValueForMarker returns the value string for a marker and the incremented index
|
||||
func (c SubstitutionCreator) extractValueForMarker(fvInd int, fv string, patternInd int, indices map[int]string) (string, int, error) {
|
||||
nonMarkerStr := strTillNextMarker(indices, patternInd, c.Pattern)
|
||||
|
||||
// return the remaining string of fv till end if patternInd is at end of pattern
|
||||
if patternInd == len(c.Pattern) {
|
||||
return fv[fvInd:], len(fv), nil
|
||||
}
|
||||
|
||||
// split remaining fv starting from fvInd with the non marker substring delimiter and get the first value
|
||||
// In example fv = "something/ubuntu::0.1.0", pattern = "something/IMAGE::VERSION",
|
||||
// split with "::" delimiter in fv which gives markerValue = ubuntu for marker IMAGE
|
||||
// increment fvInd by length of extracted marker value and return fvInd
|
||||
if markerValues := strings.Split(fv[fvInd:], nonMarkerStr); len(markerValues) > 0 {
|
||||
return markerValues[0], fvInd + len(markerValues[0]), nil
|
||||
}
|
||||
|
||||
return "", -1, errors.Errorf(
|
||||
"unable to derive values for markers," +
|
||||
" create setters for all markers and then try again")
|
||||
}
|
||||
|
||||
// substrOfLen takes a string, start index and length and returns substring of given length
|
||||
// or till end of string
|
||||
func substrOfLen(str string, startInd int, length int) string {
|
||||
return str[startInd:min(len(str), startInd+length)]
|
||||
}
|
||||
|
||||
// strTillNextMarker takes in the indices map, a start index and returns the substring till
|
||||
// start of next marker
|
||||
func strTillNextMarker(indices map[int]string, startInd int, pattern string) string {
|
||||
// initialize with max value which is length of pattern
|
||||
nextMarkerStartInd := len(pattern)
|
||||
for ind := range indices {
|
||||
if ind > startInd {
|
||||
nextMarkerStartInd = min(ind-startInd, nextMarkerStartInd)
|
||||
}
|
||||
}
|
||||
return substrOfLen(pattern, startInd, nextMarkerStartInd)
|
||||
}
|
||||
|
||||
func min(a int, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
111
kyaml/setters2/settersutil/substitutioncreator_test.go
Normal file
111
kyaml/setters2/settersutil/substitutioncreator_test.go
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package settersutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters2"
|
||||
)
|
||||
|
||||
func TestGetValuesForMarkers(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
pattern string
|
||||
fieldValue string
|
||||
markers []string
|
||||
expectedError error
|
||||
expectedOutput map[string]string
|
||||
}{
|
||||
{
|
||||
name: "positive example",
|
||||
markers: []string{"IMAGE", "VERSION"},
|
||||
pattern: "something/IMAGE::VERSION/otherthing/IMAGE::VERSION/",
|
||||
fieldValue: "something/nginx::0.1.0/otherthing/nginx::0.1.0/",
|
||||
expectedOutput: map[string]string{"IMAGE": "nginx", "VERSION": "0.1.0"},
|
||||
},
|
||||
{
|
||||
name: "marker with different values",
|
||||
markers: []string{"IMAGE", "VERSION"},
|
||||
pattern: "something/IMAGE:VERSION/IMAGE",
|
||||
fieldValue: "something/nginx:0.1.0/ubuntu",
|
||||
expectedError: errors.Errorf("marker IMAGE is found to have different values nginx and ubuntu"),
|
||||
},
|
||||
{
|
||||
name: "unmatched pattern",
|
||||
markers: []string{"IMAGE", "VERSION"},
|
||||
pattern: "something/IMAGE:VERSION",
|
||||
fieldValue: "otherthing/nginx:0.1.0",
|
||||
expectedError: errors.Errorf("unable to derive values for markers"),
|
||||
},
|
||||
{
|
||||
name: "unmatched pattern at the end",
|
||||
markers: []string{"IMAGE", "VERSION"},
|
||||
pattern: "something/IMAGE:VERSION/abc",
|
||||
fieldValue: "something/nginx:0.1.0/abcd",
|
||||
expectedError: errors.Errorf("unable to derive values for markers"),
|
||||
},
|
||||
{
|
||||
name: "substring markers",
|
||||
markers: []string{"IMAGE", "VERSION", "MAGE"},
|
||||
pattern: "something/IMAGE:VERSION/abc/MAGE",
|
||||
fieldValue: "something/nginx:0.1.0/abc/ubuntu",
|
||||
expectedError: errors.Errorf("no marker should be substring of other"),
|
||||
},
|
||||
{
|
||||
name: "markers with no delimiters",
|
||||
markers: []string{"IMAGE", "VERSION"},
|
||||
pattern: "something/IMAGEVERSION/",
|
||||
fieldValue: "something/nginx0.1.0/",
|
||||
expectedError: errors.Errorf("no delimiters between them"),
|
||||
},
|
||||
{
|
||||
name: "unmatched delimiter",
|
||||
markers: []string{"IMAGE", "VERSION"},
|
||||
pattern: "something/IMAGE:^VERSION/otherthing/IMAGE::VERSION/",
|
||||
fieldValue: "something/nginx::0.1.0/otherthing/nginx::0.1.0/",
|
||||
expectedError: errors.Errorf("unable to derive values for markers"),
|
||||
},
|
||||
}
|
||||
for i := range tests {
|
||||
test := tests[i]
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
values := []setters2.Value{}
|
||||
for _, marker := range test.markers {
|
||||
value := setters2.Value{
|
||||
Marker: marker,
|
||||
}
|
||||
values = append(values, value)
|
||||
}
|
||||
|
||||
sc := SubstitutionCreator{
|
||||
Pattern: test.pattern,
|
||||
Values: values,
|
||||
FieldValue: test.fieldValue,
|
||||
}
|
||||
|
||||
m, err := sc.GetValuesForMarkers()
|
||||
|
||||
if test.expectedError == nil {
|
||||
// fail if expectedError is nil but actual error is not
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
// check if all the expected markers and values are present in actual map
|
||||
for k, v := range test.expectedOutput {
|
||||
if val, ok := m[k]; ok {
|
||||
assert.Equal(t, v, val)
|
||||
} else {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//if expectedError is not nil, check for correctness of error message
|
||||
assert.Contains(t, err.Error(), test.expectedError.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,9 @@ type cliExtension struct {
|
||||
}
|
||||
|
||||
type setter struct {
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Value string `yaml:"value,omitempty" json:"value,omitempty"`
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Value string `yaml:"value,omitempty" json:"value,omitempty"`
|
||||
EnumValues map[string]string `yaml:"enumValues,omitempty" json:"enumValues,omitempty"`
|
||||
}
|
||||
|
||||
type substitution struct {
|
||||
@@ -56,32 +57,32 @@ func getExtFromSchema(schema *spec.Schema) (*cliExtension, error) {
|
||||
|
||||
// getExtFromComment returns the cliExtension openAPI extension if it is present as
|
||||
// a comment on the field.
|
||||
func getExtFromComment(object *yaml.RNode) (*cliExtension, error) {
|
||||
func getExtFromComment(object *yaml.RNode) (*cliExtension, *spec.Schema, error) {
|
||||
// TODO(pwittrock): also use path to the field to get openapi, not just comments
|
||||
// parse comment containing the extended openapi for this field
|
||||
fm := fieldmeta.FieldMeta{}
|
||||
if err := fm.Read(object); err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
if fm.Schema.Ref.String() == "" {
|
||||
return nil, nil
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
// resolve the comment reference to the extended openapi definitions
|
||||
r, err := openapi.Resolve(&fm.Schema.Ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
if r == nil {
|
||||
// no schema found
|
||||
// TODO(pwittrock): should this be an error if it doesn't resolve?
|
||||
return nil, nil
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
// get the cli extension from the openapi (contains setter information)
|
||||
ext, err := getExtFromSchema(r)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
return ext, nil
|
||||
return ext, r, nil
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ var Filters = map[string]func() Filter{
|
||||
"AnnotationClearer": func() Filter { return &AnnotationClearer{} },
|
||||
"AnnotationGetter": func() Filter { return &AnnotationGetter{} },
|
||||
"AnnotationSetter": func() Filter { return &AnnotationSetter{} },
|
||||
"LabelSetter": func() Filter { return &LabelSetter{} },
|
||||
"ElementAppender": func() Filter { return &ElementAppender{} },
|
||||
"ElementMatcher": func() Filter { return &ElementMatcher{} },
|
||||
"FieldClearer": func() Filter { return &FieldClearer{} },
|
||||
|
||||
@@ -68,3 +68,25 @@ func (g AnnotationGetter) Filter(rn *RNode) (*RNode, error) {
|
||||
func GetAnnotation(key string) AnnotationGetter {
|
||||
return AnnotationGetter{Key: key}
|
||||
}
|
||||
|
||||
// LabelSetter sets a label at metadata.labels.
|
||||
// Creates metadata.labels if does not exist.
|
||||
type LabelSetter struct {
|
||||
Kind string `yaml:"kind,omitempty"`
|
||||
Key string `yaml:"key,omitempty"`
|
||||
Value string `yaml:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (s LabelSetter) Filter(rn *RNode) (*RNode, error) {
|
||||
// some tools get confused about the type if labels are not quoted
|
||||
v := NewScalarRNode(s.Value)
|
||||
v.YNode().Tag = "!!str"
|
||||
v.YNode().Style = yaml.SingleQuotedStyle
|
||||
return rn.Pipe(
|
||||
PathGetter{Path: []string{"metadata", "labels"}, Create: yaml.MappingNode},
|
||||
FieldSetter{Name: s.Key, Value: v})
|
||||
}
|
||||
|
||||
func SetLabel(key, value string) LabelSetter {
|
||||
return LabelSetter{Key: key, Value: value}
|
||||
}
|
||||
|
||||
63
kyaml/yaml/kfns_test.go
Normal file
63
kyaml/yaml/kfns_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var input = `apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map
|
||||
data:
|
||||
altGreeting: "Good Morning!"
|
||||
enableRisky: "false"
|
||||
`
|
||||
|
||||
func TestSetLabel(t *testing.T) {
|
||||
rn := MustParse(input)
|
||||
_, err := rn.Pipe(SetLabel("foo", "bar"))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
output := rn.MustString()
|
||||
|
||||
expected := `apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map
|
||||
labels:
|
||||
foo: 'bar'
|
||||
data:
|
||||
altGreeting: "Good Morning!"
|
||||
enableRisky: "false"
|
||||
`
|
||||
if output != expected {
|
||||
t.Fatalf("expected \n%s\nbut got \n%s\n", expected, output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnnotation(t *testing.T) {
|
||||
rn := MustParse(input)
|
||||
_, err := rn.Pipe(SetAnnotation("foo", "bar"))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
output := rn.MustString()
|
||||
|
||||
expected := `apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map
|
||||
annotations:
|
||||
foo: 'bar'
|
||||
data:
|
||||
altGreeting: "Good Morning!"
|
||||
enableRisky: "false"
|
||||
`
|
||||
if output != expected {
|
||||
t.Fatalf("expected \n%s\nbut got \n%s\n", expected, output)
|
||||
}
|
||||
}
|
||||
@@ -4,251 +4,461 @@
|
||||
package merge2_test
|
||||
|
||||
var elementTestCases = []testCase{
|
||||
{`merge Element -- keep field in dest`,
|
||||
`
|
||||
{description: `merge Element -- keep field in dest`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
command: ['run.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
command: ['run.sh']
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Element -- add field to dest`,
|
||||
`
|
||||
{description: `merge Element -- add field to dest`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Element -- add list, empty in dest`,
|
||||
`
|
||||
{description: `merge Element -- add list, empty in dest`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items: []
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers: []
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Element -- add list, missing from dest`,
|
||||
`
|
||||
{description: `merge Element -- add list, missing from dest`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
command: ['run.sh']
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Element -- add Element first`,
|
||||
`
|
||||
{description: `merge Element -- add Element first`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Element -- add Element second`,
|
||||
`
|
||||
{description: `merge Element -- add Element second`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`keep list -- list missing from src`,
|
||||
`
|
||||
{description: `keep list -- list missing from src`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`keep Element -- element missing in src`,
|
||||
`
|
||||
{description: `keep Element -- element missing in src`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v0
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`keep element -- empty list in src`,
|
||||
`
|
||||
{description: `keep element -- empty list in src`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items: {}
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers: {}
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`remove Element -- null in src`,
|
||||
`
|
||||
{description: `remove Element -- null in src`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items: null
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers: null
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
items:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec: {}
|
||||
`,
|
||||
},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{description: `infer merge keys merge'`,
|
||||
source: `
|
||||
apiVersion: custom
|
||||
kind: Deployment
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:v1
|
||||
- name: bar
|
||||
image: bar:v1
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
apiVersion: custom
|
||||
kind: Deployment
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:bar
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: custom
|
||||
kind: Deployment
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:bar
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
infer: true,
|
||||
},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{description: `no infer merge keys merge using schema`,
|
||||
source: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
dest: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:bar
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: foo:bar
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
infer: false,
|
||||
},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{description: `no infer merge keys merge using explicit schema as line comment'`,
|
||||
source: `
|
||||
apiVersion: custom
|
||||
kind: Deployment
|
||||
containers:
|
||||
- name: foo
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
dest: `
|
||||
apiVersion: custom
|
||||
kind: Deployment
|
||||
containers: # {"items":{"$ref": "#/definitions/io.k8s.api.core.v1.Container"},"type":"array","x-kubernetes-patch-merge-key":"name","x-kubernetes-patch-strategy": "merge"}
|
||||
- name: foo # hell ow
|
||||
image: foo:bar
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: custom
|
||||
kind: Deployment
|
||||
containers: # {"items":{"$ref": "#/definitions/io.k8s.api.core.v1.Container"},"type":"array","x-kubernetes-patch-merge-key":"name","x-kubernetes-patch-strategy": "merge"}
|
||||
- name: foo
|
||||
image: foo:bar
|
||||
command: ['run2.sh']
|
||||
`,
|
||||
infer: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,21 +4,21 @@
|
||||
package merge2_test
|
||||
|
||||
var listTestCases = []testCase{
|
||||
{`replace List -- different value in dest`,
|
||||
`
|
||||
{description: `replace List -- different value in dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 0
|
||||
- 1
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
@@ -27,18 +27,18 @@ items:
|
||||
`,
|
||||
},
|
||||
|
||||
{`replace List -- missing from dest`,
|
||||
`
|
||||
{description: `replace List -- missing from dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
@@ -50,22 +50,22 @@ items:
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`keep List -- same value in src and dest`,
|
||||
`
|
||||
{description: `keep List -- same value in src and dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
@@ -77,18 +77,18 @@ items:
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`keep List -- unspecified in src`,
|
||||
`
|
||||
{description: `keep List -- unspecified in src`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
@@ -100,19 +100,19 @@ items:
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`remove List -- null in src`,
|
||||
`
|
||||
{description: `remove List -- null in src`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
items: null
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
`,
|
||||
},
|
||||
@@ -120,19 +120,19 @@ kind: Deployment
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`remove list -- empty in src`,
|
||||
`
|
||||
{description: `remove list -- empty in src`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
items: {}
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
items:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
items: {}
|
||||
`,
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
package merge2_test
|
||||
|
||||
var mapTestCases = []testCase{
|
||||
{`merge Map -- update field in dest`,
|
||||
`
|
||||
{description: `merge Map -- update field in dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar0
|
||||
baz: buz
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
@@ -24,19 +24,19 @@ spec:
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Map -- add field to dest`,
|
||||
`
|
||||
{description: `merge Map -- add field to dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
baz: buz
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar0
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
@@ -44,18 +44,18 @@ spec:
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Map -- add list, empty in dest`,
|
||||
`
|
||||
{description: `merge Map -- add list, empty in dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
baz: buz
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
spec: {}
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
@@ -63,17 +63,17 @@ spec:
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Map -- add list, missing from dest`,
|
||||
`
|
||||
{description: `merge Map -- add list, missing from dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
baz: buz
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
@@ -81,19 +81,19 @@ spec:
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Map -- add Map first`,
|
||||
`
|
||||
{description: `merge Map -- add Map first`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
baz: buz
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
@@ -101,19 +101,19 @@ spec:
|
||||
`,
|
||||
},
|
||||
|
||||
{`merge Map -- add Map second`,
|
||||
`
|
||||
{description: `merge Map -- add Map second`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
baz: buz
|
||||
foo: bar1
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
@@ -124,17 +124,17 @@ spec:
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`keep map -- map missing from src`,
|
||||
`
|
||||
{description: `keep map -- map missing from src`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
baz: buz
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
@@ -145,18 +145,18 @@ spec:
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`keep map -- empty list in src`,
|
||||
`
|
||||
{description: `keep map -- empty list in src`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
items: {}
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
baz: buz
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
@@ -168,18 +168,18 @@ items: {}
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`remove Map -- null in src`,
|
||||
`
|
||||
{description: `remove Map -- null in src`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
spec: null
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
spec:
|
||||
foo: bar1
|
||||
baz: buz
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
`,
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package merge2
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml/walk"
|
||||
)
|
||||
@@ -16,7 +17,7 @@ func Merge(src, dest *yaml.RNode) (*yaml.RNode, error) {
|
||||
}
|
||||
|
||||
// Merge parses the arguments, and merges fields from srcStr into destStr.
|
||||
func MergeStrings(srcStr, destStr string) (string, error) {
|
||||
func MergeStrings(srcStr, destStr string, infer bool) (string, error) {
|
||||
src, err := yaml.Parse(srcStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -26,10 +27,15 @@ func MergeStrings(srcStr, destStr string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result, err := Merge(src, dest)
|
||||
result, err := walk.Walker{
|
||||
Sources: []*yaml.RNode{dest, src},
|
||||
Visitor: Merger{},
|
||||
InferAssociativeLists: infer,
|
||||
}.Walk()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
@@ -39,7 +45,7 @@ type Merger struct {
|
||||
|
||||
var _ walk.Visitor = Merger{}
|
||||
|
||||
func (m Merger) VisitMap(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
func (m Merger) VisitMap(nodes walk.Sources, s *openapi.ResourceSchema) (*yaml.RNode, error) {
|
||||
if err := m.SetComments(nodes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -58,7 +64,7 @@ func (m Merger) VisitMap(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
return nodes.Dest(), nil
|
||||
}
|
||||
|
||||
func (m Merger) VisitScalar(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
func (m Merger) VisitScalar(nodes walk.Sources, s *openapi.ResourceSchema) (*yaml.RNode, error) {
|
||||
if err := m.SetComments(nodes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -73,7 +79,7 @@ func (m Merger) VisitScalar(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
return nodes.Dest(), nil
|
||||
}
|
||||
|
||||
func (m Merger) VisitList(nodes walk.Sources, kind walk.ListKind) (*yaml.RNode, error) {
|
||||
func (m Merger) VisitList(nodes walk.Sources, s *openapi.ResourceSchema, kind walk.ListKind) (*yaml.RNode, error) {
|
||||
if err := m.SetComments(nodes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ a:
|
||||
b:
|
||||
# header comment
|
||||
c: d
|
||||
`)
|
||||
`, true)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
@@ -385,7 +385,7 @@ a:
|
||||
b:
|
||||
c: d
|
||||
# footer comment
|
||||
`)
|
||||
`, true)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
@@ -404,7 +404,7 @@ a:
|
||||
a:
|
||||
b:
|
||||
c: d # line comment
|
||||
`)
|
||||
`, true)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
@@ -426,7 +426,7 @@ a:
|
||||
b:
|
||||
# replace comment
|
||||
c: d
|
||||
`)
|
||||
`, true)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
@@ -447,7 +447,7 @@ a:
|
||||
b:
|
||||
c: d
|
||||
# replace comment
|
||||
`)
|
||||
`, true)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
@@ -466,7 +466,7 @@ a:
|
||||
a:
|
||||
b:
|
||||
c: d # replace comment
|
||||
`)
|
||||
`, true)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
@@ -484,7 +484,7 @@ a:
|
||||
a:
|
||||
b:
|
||||
c: d # replace comment
|
||||
`)
|
||||
`, true)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -17,24 +17,27 @@ var testCases = [][]testCase{scalarTestCases, listTestCases, elementTestCases, m
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
for i := range testCases {
|
||||
for _, tc := range testCases[i] {
|
||||
actual, err := MergeStrings(tc.source, tc.dest)
|
||||
if !assert.NoError(t, err, tc.description) {
|
||||
t.FailNow()
|
||||
}
|
||||
e, err := filters.FormatInput(bytes.NewBufferString(tc.expected))
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
estr := strings.TrimSpace(e.String())
|
||||
a, err := filters.FormatInput(bytes.NewBufferString(actual))
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
astr := strings.TrimSpace(a.String())
|
||||
if !assert.Equal(t, estr, astr, tc.description) {
|
||||
t.FailNow()
|
||||
}
|
||||
for j := range testCases[i] {
|
||||
tc := testCases[i][j]
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
actual, err := MergeStrings(tc.source, tc.dest, tc.infer)
|
||||
if !assert.NoError(t, err, tc.description) {
|
||||
t.FailNow()
|
||||
}
|
||||
e, err := filters.FormatInput(bytes.NewBufferString(tc.expected))
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
estr := strings.TrimSpace(e.String())
|
||||
a, err := filters.FormatInput(bytes.NewBufferString(actual))
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
astr := strings.TrimSpace(a.String())
|
||||
if !assert.Equal(t, estr, astr, tc.description) {
|
||||
t.FailNow()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,4 +47,5 @@ type testCase struct {
|
||||
source string
|
||||
dest string
|
||||
expected string
|
||||
infer bool
|
||||
}
|
||||
|
||||
@@ -4,30 +4,30 @@
|
||||
package merge2_test
|
||||
|
||||
var scalarTestCases = []testCase{
|
||||
{`replace scalar -- different value in dest`,
|
||||
`
|
||||
{description: `replace scalar -- different value in dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
field: value0
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
},
|
||||
|
||||
{`replace scalar -- missing from dest`,
|
||||
`
|
||||
{description: `replace scalar -- missing from dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
@@ -36,16 +36,16 @@ field: value1
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`keep scalar -- same value in src and dest`,
|
||||
`
|
||||
{description: `keep scalar -- same value in src and dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
@@ -54,15 +54,15 @@ field: value1
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`keep scalar -- unspecified in src`,
|
||||
`
|
||||
{description: `keep scalar -- unspecified in src`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
@@ -71,16 +71,16 @@ field: value1
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`remove scalar -- null in src`,
|
||||
`
|
||||
{description: `remove scalar -- null in src`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
field: null
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
`,
|
||||
},
|
||||
@@ -88,16 +88,16 @@ kind: Deployment
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`remove scalar -- empty in src`,
|
||||
`
|
||||
{description: `remove scalar -- empty in src`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
field: {}
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
field: value1
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
field: {}
|
||||
`,
|
||||
@@ -106,15 +106,15 @@ field: {}
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`remove scalar -- null in src, missing in dest`,
|
||||
`
|
||||
{description: `remove scalar -- null in src, missing in dest`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
field: null
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
`,
|
||||
},
|
||||
@@ -122,15 +122,15 @@ kind: Deployment
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`merge an empty value`,
|
||||
`
|
||||
{description: `merge an empty value`,
|
||||
source: `
|
||||
kind: Deployment
|
||||
field: {}
|
||||
`,
|
||||
`
|
||||
dest: `
|
||||
kind: Deployment
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
field: {}
|
||||
`,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,224 +9,226 @@ var listTestCases = []testCase{
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Replace list`,
|
||||
`
|
||||
{description: `Replace list`,
|
||||
origin: `
|
||||
list:
|
||||
- 1
|
||||
- 2
|
||||
- 3`,
|
||||
`
|
||||
update: `
|
||||
list:
|
||||
- 2
|
||||
- 3
|
||||
- 4`,
|
||||
`
|
||||
local: `
|
||||
list:
|
||||
- 1
|
||||
- 2
|
||||
- 3`,
|
||||
`
|
||||
expected: `
|
||||
list:
|
||||
- 2
|
||||
- 3
|
||||
- 4`, nil},
|
||||
- 4`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Add an updated list`,
|
||||
`
|
||||
{description: `Add an updated list`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
list: # old value
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
list: # new value
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
list:
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
`, nil},
|
||||
`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Add keep an omitted field`,
|
||||
`
|
||||
{description: `Add keep an omitted field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
list: # not present in sources
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
list: # not present in sources
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
kind: StatefulSet
|
||||
`, nil},
|
||||
`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
// TODO(#36): consider making this an error
|
||||
{`Change an updated field`,
|
||||
`
|
||||
{description: `Change an updated field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
list: # old value
|
||||
- 1
|
||||
- 2
|
||||
- 3`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
list: # new value
|
||||
- 2
|
||||
- 3
|
||||
- 4`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
list: # conflicting value
|
||||
- a
|
||||
- b
|
||||
- c`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
list: # conflicting value
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
`, nil},
|
||||
`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Ignore a field -- set`,
|
||||
`
|
||||
{description: `Ignore a field -- set`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
list: # ignore value
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
list: # ignore value
|
||||
- 1
|
||||
- 2
|
||||
- 3`, `
|
||||
- 3`,
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
list:
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
`, `
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
list:
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
`, nil},
|
||||
`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Ignore a field -- empty`,
|
||||
`
|
||||
{description: `Ignore a field -- empty`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
list: # ignore value
|
||||
- 1
|
||||
- 2
|
||||
- 3`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
list: # ignore value
|
||||
- 1
|
||||
- 2
|
||||
- 3`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
`, nil},
|
||||
`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Explicitly clear a field`,
|
||||
`
|
||||
{description: `Explicitly clear a field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
list: null # clear`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
list: # value to clear
|
||||
- 1
|
||||
- 2
|
||||
- 3`,
|
||||
`
|
||||
apiVersion: apps/v1`, nil},
|
||||
expected: `
|
||||
apiVersion: apps/v1`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Implicitly clear a field`,
|
||||
`
|
||||
{description: `Implicitly clear a field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
list: # clear value
|
||||
- 1
|
||||
- 2
|
||||
- 3`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
list: # old value
|
||||
- 1
|
||||
- 2
|
||||
- 3`,
|
||||
`
|
||||
apiVersion: apps/v1`, nil},
|
||||
expected: `
|
||||
apiVersion: apps/v1`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
// TODO(#36): consider making this an error
|
||||
{`Implicitly clear a changed field`,
|
||||
`
|
||||
{description: `Implicitly clear a changed field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
list: # old value
|
||||
- 1
|
||||
- 2
|
||||
- 3`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
list: # old value
|
||||
- a
|
||||
- b
|
||||
- c`,
|
||||
`
|
||||
apiVersion: apps/v1`, nil},
|
||||
expected: `
|
||||
apiVersion: apps/v1`},
|
||||
}
|
||||
|
||||
@@ -7,267 +7,267 @@ var mapTestCases = []testCase{
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Add the annotations map field`,
|
||||
`
|
||||
{description: `Add the annotations map field`,
|
||||
origin: `
|
||||
kind: Deployment`,
|
||||
`
|
||||
update: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
d: e # add these annotations
|
||||
`,
|
||||
`
|
||||
local: `
|
||||
kind: Deployment`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
d: e # add these annotations`, nil},
|
||||
d: e # add these annotations`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Add an annotation to the field`,
|
||||
`
|
||||
{description: `Add an annotation to the field`,
|
||||
origin: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b`,
|
||||
`
|
||||
update: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b
|
||||
d: e # add these annotations`,
|
||||
`
|
||||
local: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
g: h # keep these annotations`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
g: h # keep these annotations
|
||||
d: e # add these annotations`, nil},
|
||||
d: e # add these annotations`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Add an annotation to the field, field missing from dest`,
|
||||
`
|
||||
{description: `Add an annotation to the field, field missing from dest`,
|
||||
origin: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b # ignored because unchanged`,
|
||||
`
|
||||
update: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b # ignore because unchanged
|
||||
d: e`,
|
||||
`
|
||||
local: `
|
||||
kind: Deployment`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
d: e`, nil},
|
||||
d: e`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Update an annotation on the field, field messing rom the dest`,
|
||||
`
|
||||
{description: `Update an annotation on the field, field messing rom the dest`,
|
||||
origin: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b
|
||||
d: c`,
|
||||
`
|
||||
update: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b
|
||||
d: e # set these annotations`,
|
||||
`
|
||||
local: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
g: h # keep these annotations`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
g: h # keep these annotations
|
||||
d: e # set these annotations`, nil},
|
||||
d: e # set these annotations`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Add an annotation to the field, field missing from dest`,
|
||||
`
|
||||
{description: `Add an annotation to the field, field missing from dest`,
|
||||
origin: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b # ignored because unchanged`,
|
||||
`
|
||||
update: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b # ignore because unchanged
|
||||
d: e`,
|
||||
`
|
||||
local: `
|
||||
kind: Deployment`,
|
||||
`
|
||||
expected: `
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
d: e`, nil},
|
||||
d: e`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Remove an annotation`,
|
||||
`
|
||||
{description: `Remove an annotation`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations: {}`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
c: d
|
||||
a: b`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
c: d`, nil},
|
||||
c: d`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
// TODO(#36) support ~annotations~: {} deletion
|
||||
{`Specify a field as empty that isn't present in the source`,
|
||||
`
|
||||
{description: `Specify a field as empty that isn't present in the source`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo
|
||||
annotations: null`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo
|
||||
annotations:
|
||||
a: b`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo`, nil},
|
||||
name: foo`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Remove an annotation`,
|
||||
`
|
||||
{description: `Remove an annotation`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
c: d
|
||||
a: b`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
c: d`, nil},
|
||||
c: d`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Remove annotations field`,
|
||||
`
|
||||
{description: `Remove annotations field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo
|
||||
`, nil},
|
||||
`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Remove annotations field, but keep in dest`,
|
||||
`
|
||||
{description: `Remove annotations field, but keep in dest`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
a: b`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo
|
||||
annotations:
|
||||
foo: bar # keep this annotation even though the parent field was removed`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo
|
||||
annotations:
|
||||
foo: bar # keep this annotation even though the parent field was removed`, nil},
|
||||
foo: bar # keep this annotation even though the parent field was removed`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Remove annotations, but they are already empty`,
|
||||
`
|
||||
{description: `Remove annotations, but they are already empty`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
@@ -275,24 +275,24 @@ metadata:
|
||||
annotations:
|
||||
a: b
|
||||
`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo
|
||||
`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo
|
||||
annotations: {}
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: foo
|
||||
annotations: {}
|
||||
`, nil},
|
||||
`},
|
||||
}
|
||||
|
||||
@@ -13,11 +13,12 @@ import (
|
||||
func Merge(dest, original, update *yaml.RNode) (*yaml.RNode, error) {
|
||||
// if update == nil && original != nil => declarative deletion
|
||||
|
||||
return walk.Walker{Visitor: Visitor{},
|
||||
return walk.Walker{
|
||||
Visitor: Visitor{},
|
||||
Sources: []*yaml.RNode{dest, original, update}}.Walk()
|
||||
}
|
||||
|
||||
func MergeStrings(dest, original, update string) (string, error) {
|
||||
func MergeStrings(dest, original, update string, infer bool) (string, error) {
|
||||
srcOriginal, err := yaml.Parse(original)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -31,7 +32,10 @@ func MergeStrings(dest, original, update string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result, err := Merge(d, srcOriginal, srcUpdated)
|
||||
result, err := walk.Walker{
|
||||
InferAssociativeLists: infer,
|
||||
Visitor: Visitor{},
|
||||
Sources: []*yaml.RNode{d, srcOriginal, srcUpdated}}.Walk()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -15,24 +15,27 @@ var testCases = [][]testCase{scalarTestCases, listTestCases, mapTestCases, eleme
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
for i := range testCases {
|
||||
for _, tc := range testCases[i] {
|
||||
actual, err := MergeStrings(tc.local, tc.origin, tc.update)
|
||||
if tc.err == nil {
|
||||
if !assert.NoError(t, err, tc.description) {
|
||||
t.FailNow()
|
||||
for j := range testCases[i] {
|
||||
tc := testCases[i][j]
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
actual, err := MergeStrings(tc.local, tc.origin, tc.update, tc.infer)
|
||||
if tc.err == nil {
|
||||
if !assert.NoError(t, err, tc.description) {
|
||||
t.FailNow()
|
||||
}
|
||||
if !assert.Equal(t,
|
||||
strings.TrimSpace(tc.expected), strings.TrimSpace(actual), tc.description) {
|
||||
t.FailNow()
|
||||
}
|
||||
} else {
|
||||
if !assert.Errorf(t, err, tc.description) {
|
||||
t.FailNow()
|
||||
}
|
||||
if !assert.Contains(t, tc.err.Error(), err.Error()) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
if !assert.Equal(t,
|
||||
strings.TrimSpace(tc.expected), strings.TrimSpace(actual), tc.description) {
|
||||
t.FailNow()
|
||||
}
|
||||
} else {
|
||||
if !assert.Errorf(t, err, tc.description) {
|
||||
t.FailNow()
|
||||
}
|
||||
if !assert.Contains(t, tc.err.Error(), err.Error()) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,4 +47,5 @@ type testCase struct {
|
||||
local string
|
||||
expected string
|
||||
err error
|
||||
infer bool
|
||||
}
|
||||
|
||||
@@ -8,128 +8,128 @@ var scalarTestCases = []testCase{
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Set and updated a field`,
|
||||
`kind: Deployment`,
|
||||
`kind: StatefulSet`,
|
||||
`kind: Deployment`,
|
||||
`kind: StatefulSet`, nil},
|
||||
{description: `Set and updated a field`,
|
||||
origin: `kind: Deployment`,
|
||||
update: `kind: StatefulSet`,
|
||||
local: `kind: Deployment`,
|
||||
expected: `kind: StatefulSet`},
|
||||
|
||||
{`Add an updated field`,
|
||||
`
|
||||
{description: `Add an updated field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment # old value`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet # new value`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet # new value`, nil},
|
||||
kind: StatefulSet # new value`},
|
||||
|
||||
{`Add keep an omitted field`,
|
||||
`
|
||||
{description: `Add keep an omitted field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
spec: foo # field not present in source
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
spec: foo # field not present in source
|
||||
kind: StatefulSet
|
||||
`, nil},
|
||||
`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
// TODO(#36): consider making this an error
|
||||
{`Change an updated field`,
|
||||
`
|
||||
{description: `Change an updated field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment # old value`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet # new value`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: Service # conflicting value`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet # new value`, nil},
|
||||
kind: StatefulSet # new value`},
|
||||
|
||||
{`Ignore a field`,
|
||||
`
|
||||
{description: `Ignore a field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment # ignore this field`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment # ignore this field`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1`,
|
||||
`
|
||||
apiVersion: apps/v1`, nil},
|
||||
expected: `
|
||||
apiVersion: apps/v1`},
|
||||
|
||||
{`Explicitly clear a field`,
|
||||
`
|
||||
{description: `Explicitly clear a field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: null # clear this value`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment # value to be cleared`,
|
||||
`
|
||||
apiVersion: apps/v1`, nil},
|
||||
expected: `
|
||||
apiVersion: apps/v1`},
|
||||
|
||||
{`Implicitly clear a field`,
|
||||
`
|
||||
{description: `Implicitly clear a field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment # clear this field`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment # clear this field`,
|
||||
`
|
||||
apiVersion: apps/v1`, nil},
|
||||
expected: `
|
||||
apiVersion: apps/v1`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
// TODO(#36): consider making this an error
|
||||
{`Implicitly clear a changed field`,
|
||||
`
|
||||
{description: `Implicitly clear a changed field`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet`,
|
||||
`
|
||||
apiVersion: apps/v1`, nil},
|
||||
expected: `
|
||||
apiVersion: apps/v1`},
|
||||
|
||||
//
|
||||
// Test Case
|
||||
//
|
||||
{`Merge an empty scalar value`,
|
||||
`
|
||||
{description: `Merge an empty scalar value`,
|
||||
origin: `
|
||||
apiVersion: apps/v1
|
||||
`,
|
||||
`
|
||||
update: `
|
||||
apiVersion: apps/v1
|
||||
kind: {}
|
||||
`,
|
||||
`
|
||||
local: `
|
||||
apiVersion: apps/v1
|
||||
`,
|
||||
`
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: {}
|
||||
`, nil},
|
||||
`},
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package merge3
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml/walk"
|
||||
)
|
||||
@@ -17,7 +18,7 @@ const (
|
||||
|
||||
type Visitor struct{}
|
||||
|
||||
func (m Visitor) VisitMap(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
func (m Visitor) VisitMap(nodes walk.Sources, s *openapi.ResourceSchema) (*yaml.RNode, error) {
|
||||
if yaml.IsNull(nodes.Updated()) || yaml.IsNull(nodes.Dest()) {
|
||||
// explicitly cleared from either dest or update
|
||||
return walk.ClearNode, nil
|
||||
@@ -36,7 +37,7 @@ func (m Visitor) VisitMap(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
return nodes.Dest(), nil
|
||||
}
|
||||
|
||||
func (m Visitor) visitAList(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
func (m Visitor) visitAList(nodes walk.Sources, _ *openapi.ResourceSchema) (*yaml.RNode, error) {
|
||||
if yaml.IsEmpty(nodes.Updated()) && !yaml.IsEmpty(nodes.Origin()) {
|
||||
// implicitly cleared from update -- element was deleted
|
||||
return walk.ClearNode, nil
|
||||
@@ -51,7 +52,7 @@ func (m Visitor) visitAList(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
return nodes.Dest(), nil
|
||||
}
|
||||
|
||||
func (m Visitor) VisitScalar(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
func (m Visitor) VisitScalar(nodes walk.Sources, s *openapi.ResourceSchema) (*yaml.RNode, error) {
|
||||
if yaml.IsNull(nodes.Updated()) || yaml.IsNull(nodes.Dest()) {
|
||||
// explicitly cleared from either dest or update
|
||||
return nil, nil
|
||||
@@ -103,9 +104,9 @@ func (m Visitor) visitNAList(nodes walk.Sources) (*yaml.RNode, error) {
|
||||
return nodes.Dest(), nil
|
||||
}
|
||||
|
||||
func (m Visitor) VisitList(nodes walk.Sources, kind walk.ListKind) (*yaml.RNode, error) {
|
||||
func (m Visitor) VisitList(nodes walk.Sources, s *openapi.ResourceSchema, kind walk.ListKind) (*yaml.RNode, error) {
|
||||
if kind == walk.AssociativeList {
|
||||
return m.visitAList(nodes)
|
||||
return m.visitAList(nodes, s)
|
||||
}
|
||||
// non-associative list
|
||||
return m.visitNAList(nodes)
|
||||
|
||||
34
kyaml/yaml/schema/schema.go
Normal file
34
kyaml/yaml/schema/schema.go
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package schema contains libraries for working with the yaml and openapi packages.
|
||||
package schema
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
// IsAssociative returns true if all elements in the list contain an AssociativeSequenceKey
|
||||
// as a field.
|
||||
func IsAssociative(schema *openapi.ResourceSchema, nodes []*yaml.RNode, infer bool) bool {
|
||||
if schema != nil {
|
||||
// use the schema to identify if the list is associative
|
||||
s, _ := schema.PatchStrategyAndKey()
|
||||
return s == "merge"
|
||||
}
|
||||
if !infer {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range nodes {
|
||||
node := nodes[i]
|
||||
if yaml.IsEmpty(node) {
|
||||
continue
|
||||
}
|
||||
if node.IsAssociative() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -651,24 +651,8 @@ func (rn *RNode) VisitElements(fn func(node *RNode) error) error {
|
||||
// The order sets the precedence of the merge keys -- if multiple keys are present
|
||||
// in Resources in a list, then the FIRST key which ALL elements in the list have is used as the
|
||||
// associative key for merging that list.
|
||||
var AssociativeSequenceKeys = []string{
|
||||
"mountPath", "devicePath", "ip", "type", "topologyKey", "name", "containerPort",
|
||||
}
|
||||
|
||||
// IsAssociative returns true if all elements in the list contain an AssociativeSequenceKey
|
||||
// as a field.
|
||||
func IsAssociative(nodes []*RNode) bool {
|
||||
for i := range nodes {
|
||||
node := nodes[i]
|
||||
if IsEmpty(node) {
|
||||
continue
|
||||
}
|
||||
if node.IsAssociative() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
// Only infer name as a merge key.
|
||||
var AssociativeSequenceKeys = []string{"name"}
|
||||
|
||||
// IsAssociative returns true if the RNode contains an AssociativeSequenceKey as a field.
|
||||
func (rn *RNode) IsAssociative() bool {
|
||||
|
||||
@@ -7,28 +7,44 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/sets"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
func (l *Walker) walkAssociativeSequence() (*yaml.RNode, error) {
|
||||
// may require initializing the dest node
|
||||
dest, err := l.Sources.setDestNode(l.VisitList(l.Sources, AssociativeList))
|
||||
dest, err := l.Sources.setDestNode(l.VisitList(l.Sources, l.Schema, AssociativeList))
|
||||
if dest == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// find the list of elements we need to recursively walk
|
||||
key, err := l.elementKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var key string
|
||||
if l.Schema != nil {
|
||||
_, key = l.Schema.PatchStrategyAndKey()
|
||||
}
|
||||
if key == "" { // no key from the schema, try to infer one
|
||||
// find the list of elements we need to recursively walk
|
||||
key, err = l.elementKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
values := l.elementValues(key)
|
||||
|
||||
// recursively set the elements in the list
|
||||
var s *openapi.ResourceSchema
|
||||
if l.Schema != nil {
|
||||
s = l.Schema.Elements()
|
||||
}
|
||||
for _, value := range values {
|
||||
val, err := Walker{Visitor: l,
|
||||
Sources: l.elementValue(key, value)}.Walk()
|
||||
val, err := Walker{
|
||||
InferAssociativeLists: l.InferAssociativeLists,
|
||||
Visitor: l,
|
||||
Schema: s,
|
||||
Sources: l.elementValue(key, value),
|
||||
}.Walk()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ package walk
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/sets"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
@@ -18,15 +20,27 @@ import (
|
||||
// - set each source field value on l.Dest
|
||||
func (l Walker) walkMap() (*yaml.RNode, error) {
|
||||
// get the new map value
|
||||
dest, err := l.Sources.setDestNode(l.VisitMap(l.Sources))
|
||||
dest, err := l.Sources.setDestNode(l.VisitMap(l.Sources, l.Schema))
|
||||
if dest == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// recursively set the field values on the map
|
||||
for _, key := range l.fieldNames() {
|
||||
val, err := Walker{Visitor: l,
|
||||
Sources: l.fieldValue(key), Path: append(l.Path, key)}.Walk()
|
||||
var s *openapi.ResourceSchema
|
||||
if l.Schema != nil {
|
||||
s = l.Schema.Field(key)
|
||||
}
|
||||
fv, commentSch := l.fieldValue(key)
|
||||
if commentSch != nil {
|
||||
s = commentSch
|
||||
}
|
||||
val, err := Walker{
|
||||
InferAssociativeLists: l.InferAssociativeLists,
|
||||
Visitor: l,
|
||||
Schema: s,
|
||||
Sources: fv,
|
||||
Path: append(l.Path, key)}.Walk()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -42,11 +56,40 @@ func (l Walker) walkMap() (*yaml.RNode, error) {
|
||||
}
|
||||
|
||||
// valueIfPresent returns node.Value if node is non-nil, otherwise returns nil
|
||||
func (l Walker) valueIfPresent(node *yaml.MapNode) *yaml.RNode {
|
||||
func (l Walker) valueIfPresent(node *yaml.MapNode) (*yaml.RNode, *openapi.ResourceSchema) {
|
||||
if node == nil {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
return node.Value
|
||||
|
||||
// parse the schema for the field if present
|
||||
var s *openapi.ResourceSchema
|
||||
fm := fieldmeta.FieldMeta{}
|
||||
var err error
|
||||
// check the value for a schema
|
||||
if err = fm.Read(node.Value); err == nil {
|
||||
s = &openapi.ResourceSchema{Schema: &fm.Schema}
|
||||
if fm.Schema.Ref.String() != "" {
|
||||
r, err := openapi.Resolve(&fm.Schema.Ref)
|
||||
if err == nil && r != nil {
|
||||
s.Schema = r
|
||||
}
|
||||
}
|
||||
}
|
||||
// check the key for a schema -- this will be used
|
||||
// when the value is a Sequence (comments are attached)
|
||||
// to the key
|
||||
if fm.IsEmpty() {
|
||||
if err = fm.Read(node.Key); err == nil {
|
||||
s = &openapi.ResourceSchema{Schema: &fm.Schema}
|
||||
}
|
||||
if fm.Schema.Ref.String() != "" {
|
||||
r, err := openapi.Resolve(&fm.Schema.Ref)
|
||||
if err == nil && r != nil {
|
||||
s.Schema = r
|
||||
}
|
||||
}
|
||||
}
|
||||
return node.Value, s
|
||||
}
|
||||
|
||||
// fieldNames returns a sorted slice containing the names of all fields that appear in any of
|
||||
@@ -67,15 +110,20 @@ func (l Walker) fieldNames() []string {
|
||||
}
|
||||
|
||||
// fieldValue returns a slice containing each source's value for fieldName
|
||||
func (l Walker) fieldValue(fieldName string) []*yaml.RNode {
|
||||
func (l Walker) fieldValue(fieldName string) ([]*yaml.RNode, *openapi.ResourceSchema) {
|
||||
var fields []*yaml.RNode
|
||||
var sch *openapi.ResourceSchema
|
||||
for i := range l.Sources {
|
||||
if l.Sources[i] == nil {
|
||||
fields = append(fields, nil)
|
||||
continue
|
||||
}
|
||||
field := l.Sources[i].Field(fieldName)
|
||||
fields = append(fields, l.valueIfPresent(field))
|
||||
f, s := l.valueIfPresent(field)
|
||||
fields = append(fields, f)
|
||||
if sch == nil && !s.IsEmpty() {
|
||||
sch = s
|
||||
}
|
||||
}
|
||||
return fields
|
||||
return fields, sch
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ import (
|
||||
|
||||
// walkNonAssociativeSequence returns the value of VisitList
|
||||
func (l Walker) walkNonAssociativeSequence() (*yaml.RNode, error) {
|
||||
return l.VisitList(l.Sources, NonAssociateList)
|
||||
return l.VisitList(l.Sources, l.Schema, NonAssociateList)
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ import "sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
|
||||
// walkScalar returns the value of VisitScalar
|
||||
func (l Walker) walkScalar() (*yaml.RNode, error) {
|
||||
return l.VisitScalar(l.Sources)
|
||||
return l.VisitScalar(l.Sources, l.Schema)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package walk
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
@@ -16,11 +17,11 @@ const (
|
||||
|
||||
// Visitor is invoked by walk with source and destination node pairs
|
||||
type Visitor interface {
|
||||
VisitMap(nodes Sources) (*yaml.RNode, error)
|
||||
VisitMap(Sources, *openapi.ResourceSchema) (*yaml.RNode, error)
|
||||
|
||||
VisitScalar(nodes Sources) (*yaml.RNode, error)
|
||||
VisitScalar(Sources, *openapi.ResourceSchema) (*yaml.RNode, error)
|
||||
|
||||
VisitList(nodes Sources, kind ListKind) (*yaml.RNode, error)
|
||||
VisitList(Sources, *openapi.ResourceSchema, ListKind) (*yaml.RNode, error)
|
||||
}
|
||||
|
||||
// ClearNode is returned if GrepFilter should do nothing after calling Set
|
||||
|
||||
@@ -8,20 +8,30 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml/schema"
|
||||
)
|
||||
|
||||
// Filter walks the Source RNode and modifies the RNode provided to GrepFilter.
|
||||
// Walker walks the Source RNode and modifies the RNode provided to GrepFilter.
|
||||
type Walker struct {
|
||||
// Visitor is invoked by GrepFilter
|
||||
Visitor
|
||||
|
||||
Schema *openapi.ResourceSchema
|
||||
|
||||
// Source is the RNode to walk. All Source fields and associative list elements
|
||||
// will be visited.
|
||||
Sources Sources
|
||||
|
||||
// Path is the field path to the current Source Node.
|
||||
Path []string
|
||||
|
||||
// InferAssociativeLists if set to true will infer merge strategies for
|
||||
// fields which it doesn't have the schema based on the fields in the
|
||||
// list elements.
|
||||
InferAssociativeLists bool
|
||||
}
|
||||
|
||||
func (l Walker) Kind() yaml.Kind {
|
||||
@@ -35,6 +45,8 @@ func (l Walker) Kind() yaml.Kind {
|
||||
|
||||
// GrepFilter implements yaml.GrepFilter
|
||||
func (l Walker) Walk() (*yaml.RNode, error) {
|
||||
l.Schema = l.GetSchema()
|
||||
|
||||
// invoke the handler for the corresponding node type
|
||||
switch l.Kind() {
|
||||
case yaml.MappingNode:
|
||||
@@ -46,7 +58,7 @@ func (l Walker) Walk() (*yaml.RNode, error) {
|
||||
if err := yaml.ErrorIfAnyInvalidAndNonNull(yaml.SequenceNode, l.Sources...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if yaml.IsAssociative(l.Sources) {
|
||||
if schema.IsAssociative(l.Schema, l.Sources, l.InferAssociativeLists) {
|
||||
return l.walkAssociativeSequence()
|
||||
}
|
||||
return l.walkNonAssociativeSequence()
|
||||
@@ -64,6 +76,49 @@ func (l Walker) Walk() (*yaml.RNode, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (l Walker) GetSchema() *openapi.ResourceSchema {
|
||||
for i := range l.Sources {
|
||||
r := l.Sources[i]
|
||||
if yaml.IsEmpty(r) {
|
||||
continue
|
||||
}
|
||||
|
||||
fm := fieldmeta.FieldMeta{}
|
||||
if err := fm.Read(r); err == nil && !fm.IsEmpty() {
|
||||
// per-field schema, this is fine
|
||||
if fm.Schema.Ref.String() != "" {
|
||||
// resolve the reference
|
||||
s, err := openapi.Resolve(&fm.Schema.Ref)
|
||||
if err == nil && s != nil {
|
||||
fm.Schema = *s
|
||||
}
|
||||
}
|
||||
return &openapi.ResourceSchema{Schema: &fm.Schema}
|
||||
}
|
||||
}
|
||||
|
||||
if l.Schema != nil {
|
||||
return l.Schema
|
||||
}
|
||||
for i := range l.Sources {
|
||||
r := l.Sources[i]
|
||||
if yaml.IsEmpty(r) {
|
||||
continue
|
||||
}
|
||||
|
||||
m, _ := r.GetMeta()
|
||||
if m.Kind == "" || m.APIVersion == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
s := openapi.SchemaForResourceType(yaml.TypeMeta{Kind: m.Kind, APIVersion: m.APIVersion})
|
||||
if s != nil {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
DestIndex = iota
|
||||
OriginIndex
|
||||
|
||||
@@ -148,8 +148,10 @@ func (p *plugin) findContainers(obj map[string]interface{}) error {
|
||||
}
|
||||
|
||||
func isImageMatched(s, t string) bool {
|
||||
// Tag values are limited to [a-zA-Z0-9_.-].
|
||||
pattern, _ := regexp.Compile("^" + t + "(@sha256)?(:[a-zA-Z0-9_.-]*)?$")
|
||||
// Tag values are limited to [a-zA-Z0-9_.{}-].
|
||||
// Some tools like Bazel rules_k8s allow tag patterns with {} characters.
|
||||
// More info: https://github.com/bazelbuild/rules_k8s/pull/423
|
||||
pattern, _ := regexp.Compile("^" + t + "(@sha256)?(:[a-zA-Z0-9_.{}-]*)?$")
|
||||
return pattern.MatchString(s)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
# kyaml version
|
||||
export kyaml_major=0
|
||||
export kyaml_minor=0
|
||||
export kyaml_patch=12
|
||||
export kyaml_minor=1
|
||||
export kyaml_patch=0
|
||||
|
||||
# kstatus version
|
||||
export kstatus_major=0
|
||||
@@ -16,12 +16,12 @@ export kstatus_patch=1
|
||||
# kustomize api version
|
||||
export api_major=0
|
||||
export api_minor=3
|
||||
export api_patch=2
|
||||
export api_patch=3
|
||||
|
||||
# cmd/config version
|
||||
export cmd_config_major=0
|
||||
export cmd_config_minor=0
|
||||
export cmd_config_patch=12
|
||||
export cmd_config_minor=1
|
||||
export cmd_config_patch=0
|
||||
|
||||
# cmd/kubectl version
|
||||
export cmd_kubectl_major=0
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
set -e
|
||||
|
||||
# run all tests for kyaml and related commands
|
||||
targets="kyaml cmd/config cmd/kubectl functions/examples/injection-tshirt-sizes functions/examples/template-go-nginx functions/examples/template-heredoc-cockroachdb functions/examples/validator-kubeval functions/examples/validator-resource-requests"
|
||||
targets="kyaml cmd/config cmd/kubectl functions/examples/injection-tshirt-sizes functions/examples/template-go-nginx functions/examples/template-heredoc-cockroachdb functions/examples/validator-kubeval functions/examples/validator-resource-requests functions/examples/application-cr"
|
||||
for target in $targets; do
|
||||
pushd .
|
||||
cd $target
|
||||
|
||||
Reference in New Issue
Block a user