Compare commits

...

133 Commits

Author SHA1 Message Date
Jeff Regan
abb9d5a5b1 Merge pull request #2455 from monopole/add6902
Introduce ValueAddTransformer.
2020-05-10 18:23:29 -07:00
jregan
e54455705d ValueAddTransformer 2020-05-10 17:49:46 -07:00
Jeff Regan
c39cf55509 Merge pull request #2454 from monopole/valueAddFilter
add value add filter
2020-05-10 17:12:27 -07:00
jregan
1a89d09f40 add value add filter 2020-05-10 16:59:43 -07:00
Jeff Regan
4ee126c840 Merge pull request #2453 from monopole/defineNamespaceField
Define global const for metadata/namespace field
2020-05-09 18:39:03 -07:00
jregan
39cb87cf2b Define global const for metadata/namespace field 2020-05-09 18:00:26 -07:00
Jeff Regan
3c6d3845ec Merge pull request #2452 from monopole/filePathJoin
Add filesys.InsertPathPart function
2020-05-09 17:39:04 -07:00
jregan
51e3e0ff29 add filesys.InsertPathPart function 2020-05-09 17:21:31 -07:00
Jeff Regan
5c382b3c57 Merge pull request #2451 from monopole/upgradeKyaml
Upgrade to latest kyaml, cmd/config
2020-05-09 16:53:07 -07:00
jregan
065f70705d Upgrade to latest kyaml, cmd/config 2020-05-09 16:31:24 -07:00
Kubernetes Prow Robot
77fa5c2921 Merge pull request #2447 from pwittrock/release
update cmd/config e2e tests with new go function framework
2020-05-08 09:21:42 -07:00
Phillip Wittrock
cc84eb108d update cmd/config e2e tests with new go function framework 2020-05-08 09:10:15 -07:00
Kubernetes Prow Robot
2409845437 Merge pull request #2446 from pwittrock/release
release kyaml and cmd/config v0.1.10
2020-05-08 09:05:43 -07:00
Phillip Wittrock
83c7c29132 release kyaml and cmd/config v0.1.10 2020-05-08 08:51:54 -07:00
Kubernetes Prow Robot
7a03fe7353 Merge pull request #2445 from pwittrock/release
UX improvements to kyaml/fn/framework
2020-05-08 08:23:42 -07:00
Phillip Wittrock
5bae01fa68 UX improvements to kyaml/fn/framework 2020-05-07 22:03:12 -07:00
Kubernetes Prow Robot
9d6bbfb38a Merge pull request #2437 from phanimarupaka/ValidationSubstName
Avoid Setter and Substitution with same name
2020-05-07 14:09:42 -07:00
Kubernetes Prow Robot
dac97f6aeb Merge pull request #2439 from phanimarupaka/ListSubstitions
List substitutions
2020-05-07 13:55:42 -07:00
phani
1494cd3702 Merge branch 'master' into ListSubstitions 2020-05-07 13:38:18 -07:00
Kubernetes Prow Robot
3dfc76b769 Merge pull request #2436 from pwittrock/exec
Refactor function runtimes into a single package
2020-05-07 13:33:42 -07:00
Phillip Wittrock
dab0f3cf22 Add documentation and simplify framework 2020-05-07 12:51:02 -07:00
Kubernetes Prow Robot
8d5fc2f281 Merge pull request #2397 from sunny0826/docs
Update zh docs
2020-05-07 10:43:09 -07:00
Kubernetes Prow Robot
9b26390d92 Merge pull request #2433 from webwurst/patch-2
Fix typo
2020-05-06 13:33:08 -07:00
Phani Teja Marupaka
7309a5cb06 Suggested Changes 2020-05-06 12:38:12 -07:00
Kubernetes Prow Robot
099b6ff460 Merge pull request #2441 from phanimarupaka/DoNotModifyCM
Do not modify CM and Secrets Generator
2020-05-06 12:21:09 -07:00
Phani Teja Marupaka
7d600c1c5a Do not modify CM and Secrets Generator 2020-05-06 09:38:33 -07:00
Phillip Wittrock
259624ac07 run e2e tests in GitHub Actions CI 2020-05-06 08:59:54 -07:00
Phillip Wittrock
d16d1f81b0 add starlark e2e tests 2020-05-06 08:59:54 -07:00
Phillip Wittrock
b3ff51b9bc Add warnings for exec functions 2020-05-06 08:59:54 -07:00
Phillip Wittrock
c9f50745ff e2e tests for functions 2020-05-06 08:59:54 -07:00
Phillip Wittrock
95f0a44fc0 Enable exec functions (Alpha) 2020-05-06 08:59:54 -07:00
Phillip Wittrock
174b2ed62e Refactor starlark runtime ontop of runtimeutil 2020-05-06 08:16:14 -07:00
Phillip Wittrock
594c48d19a Refactor container function runtime into its own package 2020-05-06 08:16:14 -07:00
Phillip Wittrock
096ad8c95c Exec function implementation 2020-05-06 08:16:14 -07:00
Phillip Wittrock
fd70213ca2 Create shared functions filter library 2020-05-06 08:16:14 -07:00
Jeff Regan
212ec66e91 Merge pull request #2440 from kubernetes-sigs/pwittrock-patch-1
Create go.yml
2020-05-06 07:58:45 -07:00
Phillip Wittrock
02235007e1 Create go.yml 2020-05-06 07:52:18 -07:00
Phani Teja Marupaka
6d92608877 List substitutions 2020-05-05 20:51:46 -07:00
Phani Teja Marupaka
e771902a07 Avoid Setter and Substitution with same name 2020-05-05 14:47:28 -07:00
Tobias Bradtke
2ce66c0a85 Fix typo 2020-05-03 01:23:46 +02:00
Kubernetes Prow Robot
f7909fad71 Merge pull request #2429 from pwittrock/framework
Better support for writing functions in go
2020-05-01 12:06:29 -07:00
Kubernetes Prow Robot
5e00158b00 Merge pull request #2430 from monopole/versionBump
kyaml 0.1.8, cmd/config 0.1.7
2020-04-30 16:06:06 -07:00
Jeffrey Regan
218880cdd9 kyaml 0.1.8, cmd/config 0.1.7 2020-04-30 15:51:49 -07:00
Jeff Regan
31e5ab1e6d Merge pull request #2428 from thephw/update-exampe-tests-link-in-docs
Update link to travis pre-commit hook in docs
2020-04-30 15:44:47 -07:00
Jeff Regan
a9e998d27d Merge pull request #2424 from monopole/fixErrorMessage
Improve config failure error message.
2020-04-30 15:41:04 -07:00
Phillip Wittrock
b579bf2b03 Better support for writing functions in go 2020-04-30 13:33:56 -07:00
Patrick Wiseman
cae8fd0013 Update link to travis pre-commit hook in docs 2020-04-30 12:03:47 -04:00
jregan
de9f80c41b Improve config failure error message. 2020-04-29 19:42:56 -07:00
Jeff Regan
085b64cde4 Merge pull request #2423 from justinsb/fix_mergefilter_docs
Fix godocs on MergeFilter
2020-04-29 15:36:29 -07:00
Jeff Regan
0abad97de3 Merge pull request #2419 from phanimarupaka/SettersNameForSubst
Simplify substitutions
2020-04-29 12:46:39 -07:00
Phani Teja Marupaka
a2f2cc6a85 Create setter with marker as name for subst 2020-04-29 12:20:38 -07:00
Justin SB
028811eb97 Fix godocs on MergeFilter
It was copy-pasted from GrepFilter
2020-04-29 14:13:15 -04:00
Jeff Regan
d67c03af12 Merge pull request #2421 from Shell32-Natsu/2392-codeClean
Remove inventory transformer
2020-04-29 11:03:54 -07:00
Jeff Regan
c95a89c1f1 Merge pull request #2422 from muenchdo/test/merge-env-from
add test to demonstrate kubernetes-sigs/kustomize#1835
2020-04-29 10:54:16 -07:00
Dominik Münch
499246a4a4 add test to demonstrate kubernetes-sigs/kustomize#1835 2020-04-29 09:27:23 +02:00
Jeff Regan
bd3d413ffd Merge pull request #2420 from ian-howell/replaceVars-panic
Fix a panic when doing variable replacement.
2020-04-28 11:25:42 -07:00
Donny Xia
9195f05bba Update document 2020-04-28 17:36:44 +00:00
Donny Xia
63f7495e88 Remove inventory transformer #2392 2020-04-28 17:36:44 +00:00
guoxudong
6994e41eb3 fix 2020-04-28 14:17:03 +08:00
Ian Howell
1d46edccb5 Fix a panic when doing variable replacement.
This fixes an issue where Kustomize expects a []string, but gets a slice
of something else instead, which causing a runtime panic.

This fixes 2241
2020-04-27 15:54:04 -05:00
Jeff Regan
c771f24626 Merge pull request #2389 from webwurst/patch-1
Fix formating of example
2020-04-27 10:44:33 -07:00
Kubernetes Prow Robot
3e6b5918a2 Merge pull request #2418 from monopole/annotationTransformer
Remove MapTransformer.
2020-04-25 14:59:28 -07:00
jregan
7feb873ef6 Remove MapTransformer. 2020-04-25 13:27:01 -07:00
Jeff Regan
3c72a93c21 Merge pull request #2417 from monopole/fixBuild
Disable flaky git diff checks.
2020-04-25 12:52:23 -07:00
jregan
f07cae82b0 Disable flakey git diff checks. 2020-04-25 12:37:10 -07:00
Jeff Regan
2b48c4b08d Merge pull request #2416 from aodinokov/finalize_helm_v3_support
Finalize helm v3 support
2020-04-25 12:34:01 -07:00
Alexey Odinokov
855b2c3171 Polishing helmV3 related changes
Enabled HelmV3 related test,
Made sure HelmV2 and HelmV3 UT pass,
Pinned Chart version as per TODO note
Removed accomplished TODOs
2020-04-25 04:58:14 +00:00
Jeff Regan
82f20da46e Merge pull request #2414 from monopole/migrateLabelTransformer
Migrate label transformer
2020-04-24 18:12:44 -07:00
jregan
72c7db39f2 Migrate the label transformer. 2020-04-24 17:39:52 -07:00
jregan
c852bb00f2 Special treatment for core apiVersions. 2020-04-24 15:40:44 -07:00
Jeff Regan
a5db82e3a0 Merge pull request #2411 from monopole/moarTests
More GVK tests before GV treatment changes.
2020-04-24 15:35:22 -07:00
jregan
0636368c8c More GVK tests before GV treatment changes. 2020-04-24 15:10:59 -07:00
Jeff Regan
3516bf1bb1 Merge pull request #2409 from monopole/apiVersionExtractions
Isolate apiVersion parsing.
2020-04-24 14:17:28 -07:00
jregan
d5ba8533fa Isolate apiVersion parsing. 2020-04-24 13:56:41 -07:00
Alexey Odinokov
40db077d3d updated test for helmV3 2020-04-24 05:51:23 +00:00
Alexey Odinokov
d4d95012c7 Added needed calls for HelmV3 2020-04-24 05:14:08 +00:00
Kubernetes Prow Robot
99b15004dd Merge pull request #2406 from monopole/upgradeTests
Bug hunting; add more tests high and low.
2020-04-23 17:14:07 -07:00
jregan
c777a3805d Bug hunting; add more tests high and low. 2020-04-23 16:52:12 -07:00
Kubernetes Prow Robot
52facc13ed Merge pull request #2404 from monopole/goVersion14
Adjust scripts to allow either Go v.13 or Go v1.14
2020-04-22 19:09:45 -07:00
jregan
53e7c87604 Adjust scripts to be go v1.14 compatible 2020-04-22 18:34:15 -07:00
Kubernetes Prow Robot
8618613325 Merge pull request #2402 from pwittrock/validation-spec
release kyaml and cmd/config
2020-04-22 15:19:44 -07:00
Jeff Regan
59b1662b92 Merge pull request #2401 from monopole/fixBuild
Fix broken Makefiles.
2020-04-22 13:43:58 -07:00
jregan
efeb26c634 Fix broken Makefiles. 2020-04-22 13:30:39 -07:00
Jeff Regan
e287d68d0f Merge pull request #2403 from monopole/removeGuess
Remove time guessing.
2020-04-22 13:30:09 -07:00
jregan
3786db2dba Remove time guessing. 2020-04-22 13:20:10 -07:00
Phillip Wittrock
46316198cb release kyaml and cmd/config 2020-04-22 13:08:19 -07:00
Kubernetes Prow Robot
243394002f Merge pull request #2391 from pwittrock/validation-spec
Allow declaratively running starlark functions
2020-04-22 09:27:53 -07:00
guoxudong
60f3ca6f70 update:docs/zh/README.md 2020-04-22 17:00:16 +08:00
guoxudong
5e9619d3fb update:docs/zh/fields.md 2020-04-22 16:44:50 +08:00
Jeff Regan
b9053655db Merge pull request #2395 from monopole/checkForProwNotTravis
Check for prow, not travis, in CI test.
2020-04-21 21:19:45 -07:00
jregan
1f35b37712 Check for prow, not travis, in CI test. 2020-04-21 21:09:09 -07:00
Kubernetes Prow Robot
d7484aacad Merge pull request #2394 from monopole/installHelm3
Start adding helm3 to ChartInflator and its coverage.
2020-04-21 21:03:51 -07:00
jregan
98414e8bf6 Start adding helm3 to ChartInflator and its coverage. 2020-04-21 20:45:19 -07:00
Phillip Wittrock
c1f2dd3688 Allow declaratively running starlark functions 2020-04-21 14:51:15 -07:00
Jeff Regan
982b9e77d4 Merge pull request #2372 from phanimarupaka/GitDiffForUpdate
Print file difference like git diff
2020-04-21 11:16:36 -07:00
Kubernetes Prow Robot
c75a47322b Merge pull request #2388 from monopole/removeStaticCling
Remove static cling in plugin development flow.
2020-04-20 12:13:40 -07:00
Jeff Regan
bb05d19a5a Merge pull request #2383 from novalagung/master
Issue #2381 - bug fix for unmodified `found` variable
2020-04-20 10:41:20 -07:00
Tobias Bradtke
8c18970b56 Fix formating of example 2020-04-20 18:33:22 +02:00
jregan
2c615d78a2 Remove static cling in plugin development flow. 2020-04-20 08:29:01 -07:00
Jeff Regan
45a9805656 Merge pull request #2387 from monopole/splitOutCompilerUtils
Add compiler utils test.
2020-04-19 17:56:38 -07:00
jregan
504029281a Add compiler utils test. 2020-04-19 17:44:01 -07:00
Jeff Regan
2d699f93fc Merge pull request #2385 from monopole/pluginLoader
Plugin flow doc improvements and a new option for the plugin loader
2020-04-18 19:45:16 -07:00
jregan
1653a70693 Plugin loader improvements. 2020-04-18 18:29:10 -07:00
Kubernetes Prow Robot
4667372114 Merge pull request #2384 from pwittrock/validation-spec
Enable functions to defer failures
2020-04-17 21:43:35 -07:00
Phillip Wittrock
6d9702561a Enable functions to defer failures
so multiple validators can be run sequentially without shortcircuiting the pipeline
2020-04-17 20:27:58 -07:00
novalagung
4533e43009 Issue #2381 - bug fix for unmodified found variable 2020-04-18 04:06:54 +07:00
Kubernetes Prow Robot
c7b00733c1 Merge pull request #2382 from pwittrock/release
release cmd/config and kyaml
2020-04-17 11:03:07 -07:00
Phillip Wittrock
b023570fae release cmd/config and kyaml 2020-04-17 09:51:59 -07:00
Kubernetes Prow Robot
8c315ab874 Merge pull request #2362 from pwittrock/validation-spec
Support for serializing ResourceList.results field from functions
2020-04-17 09:23:06 -07:00
Phani Teja Marupaka
014db05f9c Print file difference like git diff 2020-04-16 12:31:00 -07:00
Kubernetes Prow Robot
d8f601248b Merge pull request #2377 from monopole/patchReadability
PatchTransformer readability mods and another test.
2020-04-16 10:46:46 -07:00
Jeffrey Regan
9c75afca58 PatchTransfomer readability mods. 2020-04-15 18:48:59 -07:00
Jeff Regan
8f2f2c201f Merge pull request #2376 from monopole/updateDeps
Update deps (autogenerated)
2020-04-15 17:49:55 -07:00
Jeffrey Regan
e66235f380 Update deps. 2020-04-15 17:12:25 -07:00
Jeff Regan
636167ac7f Merge pull request #2359 from mortent/PatchTransformerFilter
Update PatchTransformer to use kyaml filters
2020-04-15 17:11:29 -07:00
Kubernetes Prow Robot
4eac2b10d6 Merge pull request #2373 from monopole/addGeneratorTest
Add coverage to the disable name hash option in generators.
2020-04-15 16:18:45 -07:00
Jeffrey Regan
d15a573544 Add Generator Test 2020-04-15 16:00:06 -07:00
Phillip Wittrock
8d22cbdcca Support writing results from container filter 2020-04-15 08:01:49 -07:00
Phillip Wittrock
b72db9e783 ByteReader/Writer support for serializing ResourceList.results field 2020-04-14 12:59:46 -07:00
Kubernetes Prow Robot
a446a4f4fe Merge pull request #2354 from phanimarupaka/KustomizeOpenApi
Kustomization openapi ConfigMapGenerator and SecretGenerator
2020-04-14 10:48:13 -07:00
Phani Teja Marupaka
f81d766584 Kustomization openapi 2020-04-13 23:21:17 -07:00
Morten Torkildsen
ef592606a0 Update PatchTransformer to use kyaml filters 2020-04-13 21:25:02 -07:00
Kubernetes Prow Robot
4e322fb501 Merge pull request #2363 from monopole/moarPatchTransformerCoverage
Add more patch transformer coverage.
2020-04-10 19:35:47 -07:00
jregan
b1e48a46c7 Add more patch transformer coverage. 2020-04-10 18:21:12 -07:00
Jeff Regan
83700461fc Merge pull request #2361 from mortent/PatchTransformerFilterTest
Update tests for PatchTransformer
2020-04-10 18:04:33 -07:00
Kubernetes Prow Robot
853181e36f Merge pull request #2360 from monopole/updateDocs
More documentation for  field.
2020-04-10 17:49:47 -07:00
Morten Torkildsen
e7e7648c55 Update tests for PatchTransformer 2020-04-10 16:12:53 -07:00
jregan
20643c933e More documentation for field. 2020-04-10 13:54:25 -07:00
Kubernetes Prow Robot
0227582684 Merge pull request #2357 from monopole/refactorGeneratorArgs
Define hash suffix behavior in the presence of multiple GeneratorOptions.
2020-04-10 11:15:47 -07:00
jregan
c4db0f9a60 checkpoint 2020-04-10 11:01:31 -07:00
Jeff Regan
5479d32aa3 Merge pull request #2353 from kubernetes-sigs/prowBadge
Show prow build instead of deprecated travis
2020-04-09 19:49:33 -07:00
Jeff Regan
6aabe72fce Merge pull request #2352 from monopole/unpinPlugins
Unpin the plugins (i.e. point them to head).
2020-04-08 19:55:38 -07:00
jregan
65b6e1c2bb Unpin the plugins (i.e. point them to head). 2020-04-08 18:01:10 -07:00
251 changed files with 11881 additions and 5871 deletions

28
.github/workflows/go.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Go
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.13
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Build
run: ./travis/kyaml-pre-commit.sh
env:
KUSTOMIZE_DOCKER_E2E: true

View File

@@ -116,7 +116,6 @@ _builtinplugins = \
ConfigMapGenerator.go \
HashTransformer.go \
ImageTagTransformer.go \
InventoryTransformer.go \
LabelTransformer.go \
LegacyOrderTransformer.go \
NamespaceTransformer.go \
@@ -125,7 +124,8 @@ _builtinplugins = \
PatchTransformer.go \
PrefixSuffixTransformer.go \
ReplicaCountTransformer.go \
SecretGenerator.go
SecretGenerator.go \
ValueAddTransformer.go
# Maintaining this explicit list of generated files, and
# adding it as a dependency to a few targets, to assure
@@ -141,7 +141,6 @@ $(pGen)/AnnotationsTransformer.go: $(pSrc)/annotationstransformer/AnnotationsTra
$(pGen)/ConfigMapGenerator.go: $(pSrc)/configmapgenerator/ConfigMapGenerator.go
$(pGen)/HashTransformer.go: $(pSrc)/hashtransformer/HashTransformer.go
$(pGen)/ImageTagTransformer.go: $(pSrc)/imagetagtransformer/ImageTagTransformer.go
$(pGen)/InventoryTransformer.go: $(pSrc)/inventorytransformer/InventoryTransformer.go
$(pGen)/LabelTransformer.go: $(pSrc)/labeltransformer/LabelTransformer.go
$(pGen)/LegacyOrderTransformer.go: $(pSrc)/legacyordertransformer/LegacyOrderTransformer.go
$(pGen)/NamespaceTransformer.go: $(pSrc)/namespacetransformer/NamespaceTransformer.go
@@ -151,6 +150,7 @@ $(pGen)/PatchTransformer.go: $(pSrc)/patchtransformer/PatchTransformer.go
$(pGen)/PrefixSuffixTransformer.go: $(pSrc)/prefixsuffixtransformer/PrefixSuffixTransformer.go
$(pGen)/ReplicaCountTransformer.go: $(pSrc)/replicacounttransformer/ReplicaCountTransformer.go
$(pGen)/SecretGenerator.go: $(pSrc)/secretgenerator/SecretGenerator.go
$(pGen)/ValueAddTransformer.go: $(pSrc)/valueaddtransformer/ValueAddTransformer.go
# The (verbose but portable) Makefile way to convert to lowercase.
toLowerCase = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))
@@ -188,8 +188,14 @@ lint-kustomize: install-tools $(builtinplugins)
cd pluginator; \
$(MYGOBIN)/golangci-lint-kustomize -c ../.golangci-kustomize.yml run ./...
# Used to add non-default compilation flags when experimenting with
# plugin-to-api compatibility checks.
.PHONY: build-kustomize-api
build-kustomize-api: $(builtinplugins)
cd api; go build ./...
.PHONY: test-unit-kustomize-api
test-unit-kustomize-api: $(builtinplugins)
test-unit-kustomize-api: build-kustomize-api
cd api; go test ./...
.PHONY: test-unit-kustomize-plugins
@@ -212,10 +218,6 @@ test-unit-cmd-all:
test-go-mod:
./travis/check-go-mod.sh
.PHONY:
test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh HEAD
.PHONY:
test-examples-e2e-kustomize: $(MYGOBIN)/mdrip $(MYGOBIN)/kind
( \
@@ -226,13 +228,17 @@ test-examples-e2e-kustomize: $(MYGOBIN)/mdrip $(MYGOBIN)/kind
./hack/testExamplesE2EAgainstKustomize.sh .; \
)
.PHONY:
test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
./hack/testExamplesAgainstKustomize.sh HEAD
.PHONY:
test-examples-kustomize-against-latest: $(MYGOBIN)/mdrip
( \
set -e; \
/bin/rm -f $(MYGOBIN)/kustomize; \
echo "Installing kustomize from latest."; \
GO111MODULE=on go install sigs.k8s.io/kustomize/kustomize/v3; \
GO111MODULE=on go get sigs.k8s.io/kustomize/kustomize/v3@v3.5.4; \
./hack/testExamplesAgainstKustomize.sh latest; \
echo "Reinstalling kustomize from HEAD."; \
cd kustomize; go install .; \
@@ -255,21 +261,38 @@ $(MYGOBIN)/kubeval:
)
# linux only.
# This is for testing an example plugin that
# uses helm to inflate a chart for subsequent kustomization.
# Don't want to add a hard dependence in go.mod file
# to helm.
# Instead, download the binary.
$(MYGOBIN)/helm:
# This is for testing an example plugin that uses helm to inflate a chart
# for subsequent kustomization.
# Don't want to add a hard dependence in go.mod file to helm.
# Instead, download the binaries.
$(MYGOBIN)/helmV2:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz; \
tar -xvzf helm-v2.13.1-linux-amd64.tar.gz; \
mv linux-amd64/helm $(MYGOBIN); \
tgzFile=helm-v2.13.1-linux-amd64.tar.gz; \
wget https://storage.googleapis.com/kubernetes-helm/$$tgzFile; \
tar -xvzf $$tgzFile; \
mv linux-amd64/helm $(MYGOBIN)/helmV2; \
rm -rf $$d \
)
# Helm V3 differs from helm V2; downloading it to provide coverage for the
# chart inflator plugin under helm v3.
$(MYGOBIN)/helmV3:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
tgzFile=helm-v3.2.0-rc.1-linux-amd64.tar.gz; \
wget https://get.helm.sh/$$tgzFile; \
tar -xvzf $$tgzFile; \
mv linux-amd64/helm $(MYGOBIN)/helmV3; \
rm -rf $$d \
)
# Default version of helm is v2 for the time being.
$(MYGOBIN)/helm: $(MYGOBIN)/helmV2
ln -s $(MYGOBIN)/helmV2 $(MYGOBIN)/helm
$(MYGOBIN)/kind:
( \
set -e; \
@@ -288,6 +311,7 @@ clean: kustomize-external-go-plugin-clean
rm -f $(MYGOBIN)/kustomize
rm -f $(MYGOBIN)/golangci-lint-kustomize
# Nuke the site from orbit. It's the only way to be sure.
.PHONY: nuke
nuke: clean
sudo rm -rf $(shell go env GOPATH)/pkg/mod/sigs.k8s.io
go clean --modcache

View File

@@ -6,7 +6,6 @@ package builtins
import (
"sigs.k8s.io/kustomize/api/filters/annotations"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/transform"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
@@ -16,10 +15,6 @@ import (
type AnnotationsTransformerPlugin struct {
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
// YAMLSupport can be set to true to use the kyaml filter instead of the
// kunstruct transformer
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *AnnotationsTransformerPlugin) Config(
@@ -30,27 +25,16 @@ func (p *AnnotationsTransformerPlugin) Config(
}
func (p *AnnotationsTransformerPlugin) Transform(m resmap.ResMap) error {
if p.YAMLSupport {
for _, r := range m.Resources() {
err := filtersutil.ApplyToJSON(annotations.Filter{
Annotations: p.Annotations,
FsSlice: p.FieldSpecs,
}, r.Kunstructured)
if err != nil {
return err
}
}
return nil
} else {
t, err := transform.NewMapTransformer(
p.FieldSpecs,
p.Annotations,
)
for _, r := range m.Resources() {
err := filtersutil.ApplyToJSON(annotations.Filter{
Annotations: p.Annotations,
FsSlice: p.FieldSpecs,
}, r.Kunstructured)
if err != nil {
return err
}
return t.Transform(m)
}
return nil
}
func NewAnnotationsTransformerPlugin() resmap.TransformerPlugin {

View File

@@ -13,13 +13,10 @@ import (
type ConfigMapGeneratorPlugin struct {
h *resmap.PluginHelpers
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
types.GeneratorOptions
types.ConfigMapArgs
}
func (p *ConfigMapGeneratorPlugin) Config(
h *resmap.PluginHelpers, config []byte) (err error) {
p.GeneratorOptions = types.GeneratorOptions{}
func (p *ConfigMapGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
p.ConfigMapArgs = types.ConfigMapArgs{}
err = yaml.Unmarshal(config, p)
if p.ConfigMapArgs.Name == "" {
@@ -34,8 +31,7 @@ func (p *ConfigMapGeneratorPlugin) Config(
func (p *ConfigMapGeneratorPlugin) Generate() (resmap.ResMap, error) {
return p.h.ResmapFactory().FromConfigMapArgs(
kv.NewLoader(p.h.Loader(), p.h.Validator()),
&p.GeneratorOptions, p.ConfigMapArgs)
kv.NewLoader(p.h.Loader(), p.h.Validator()), p.ConfigMapArgs)
}
func NewConfigMapGeneratorPlugin() resmap.GeneratorPlugin {

View File

@@ -1,128 +0,0 @@
// Code generated by pluginator on InventoryTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/hasher"
"sigs.k8s.io/kustomize/api/inventory"
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
)
type InventoryTransformerPlugin struct {
h *resmap.PluginHelpers
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Policy string `json:"policy,omitempty" yaml:"policy,omitempty"`
}
func (p *InventoryTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
p.h = h
err = yaml.Unmarshal(c, p)
if err != nil {
return err
}
if p.Policy == "" {
p.Policy = types.GarbageIgnore.String()
}
if p.Policy != types.GarbageCollect.String() &&
p.Policy != types.GarbageIgnore.String() {
return fmt.Errorf(
"unrecognized garbagePolicy '%s'", p.Policy)
}
return nil
}
// Transform generates an inventory object from the input ResMap.
// This ConfigMap supports the pruning command in
// the client side tool proposed here:
// https://github.com/kubernetes/enhancements/pull/810
//
// The inventory data is written to the ConfigMap's
// annotations, rather than to the key-value pairs in
// the ConfigMap's data field, since
// 1. Keys in a ConfigMap's data field are too
// constrained for this purpose.
// 2. Using annotations allow any object to be used,
// not just a ConfigMap, should some other object
// (e.g. some App object) become more desirable
// for this purpose.
func (p *InventoryTransformerPlugin) Transform(m resmap.ResMap) error {
inv, h, err := makeInventory(m)
if err != nil {
return err
}
args := types.ConfigMapArgs{}
args.Name = p.Name
args.Namespace = p.Namespace
opts := &types.GeneratorOptions{
Annotations: make(map[string]string),
}
opts.Annotations[inventory.HashAnnotation] = h
err = inv.UpdateAnnotations(opts.Annotations)
if err != nil {
return err
}
cm, err := p.h.ResmapFactory().RF().MakeConfigMap(
kv.NewLoader(p.h.Loader(), p.h.Validator()), opts, &args)
if err != nil {
return err
}
if p.Policy == types.GarbageCollect.String() {
for _, byeBye := range m.AllIds() {
m.Remove(byeBye)
}
}
return m.Append(cm)
}
func makeInventory(m resmap.ResMap) (
inv *inventory.Inventory, hash string, err error) {
inv = inventory.NewInventory()
var keys []string
for _, r := range m.Resources() {
ns := r.GetNamespace()
item := resid.NewResIdWithNamespace(r.GetGvk(), r.GetName(), ns)
if _, ok := inv.Current[item]; ok {
return nil, "", fmt.Errorf(
"item '%v' already in inventory", item)
}
inv.Current[item], err = computeRefs(r, m)
if err != nil {
return nil, "", err
}
keys = append(keys, item.String())
}
h, err := hasher.SortArrayAndComputeHash(keys)
return inv, h, err
}
func computeRefs(
r *resource.Resource, m resmap.ResMap) (refs []resid.ResId, err error) {
for _, refid := range r.GetRefBy() {
ref, err := m.GetByCurrentId(refid)
if err != nil {
return nil, err
}
refs = append(
refs,
resid.NewResIdWithNamespace(
ref.GetGvk(), ref.GetName(), ref.GetNamespace()))
}
return
}
func NewInventoryTransformerPlugin() resmap.TransformerPlugin {
return &InventoryTransformerPlugin{}
}

View File

@@ -4,9 +4,10 @@
package builtins
import (
"sigs.k8s.io/kustomize/api/filters/labels"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/transform"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -24,14 +25,16 @@ func (p *LabelTransformerPlugin) Config(
}
func (p *LabelTransformerPlugin) Transform(m resmap.ResMap) error {
t, err := transform.NewMapTransformer(
p.FieldSpecs,
p.Labels,
)
if err != nil {
return err
for _, r := range m.Resources() {
err := filtersutil.ApplyToJSON(labels.Filter{
Labels: p.Labels,
FsSlice: p.FieldSpecs,
}, r.Kunstructured)
if err != nil {
return err
}
}
return t.Transform(m)
return nil
}
func NewLabelTransformerPlugin() resmap.TransformerPlugin {

View File

@@ -46,19 +46,7 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
id := r.OrgId()
if !p.YAMLSupport {
// use the old style transform
applicableFs := p.applicableFieldSpecs(id)
for _, fs := range applicableFs {
err := transform.MutateField(
r.Map(), fs.PathSlice(), fs.CreateIfNotPresent,
p.changeNamespace(r))
if err != nil {
return err
}
}
} else {
if p.YAMLSupport {
// use the new style transform
err := filtersutil.ApplyToJSON(namespace.Filter{
Namespace: p.Namespace,
@@ -67,18 +55,28 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
if err != nil {
return err
}
} else {
// use the old style transform
applicableFs := p.applicableFieldSpecs(id)
for _, fs := range applicableFs {
err := transform.MutateField(
r.Map(), fs.PathSlice(), fs.CreateIfNotPresent,
p.changeNamespace(r))
if err != nil {
return err
}
}
}
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
if len(matches) != 1 {
return fmt.Errorf("namespace transformation produces ID conflict: %+v", matches)
return fmt.Errorf(
"namespace transformation produces ID conflict: %+v", matches)
}
}
return nil
}
const metaNamespace = "metadata/namespace"
// Special casing metadata.namespace since
// all objects have it, even "ClusterKind" objects
// that don't exist in a namespace (the Namespace
@@ -86,7 +84,9 @@ const metaNamespace = "metadata/namespace"
func (p *NamespaceTransformerPlugin) applicableFieldSpecs(id resid.ResId) []types.FieldSpec {
var res []types.FieldSpec
for _, fs := range p.FieldSpecs {
if id.IsSelected(&fs.Gvk) && (fs.Path != metaNamespace || (fs.Path == metaNamespace && id.IsNamespaceableKind())) {
if id.IsSelected(&fs.Gvk) &&
(fs.Path != types.MetadataNamespacePath ||
(fs.Path == types.MetadataNamespacePath && id.IsNamespaceableKind())) {
res = append(res, fs)
}
}

View File

@@ -5,12 +5,16 @@ package builtins
import (
"fmt"
"strings"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
@@ -20,69 +24,112 @@ type PatchTransformerPlugin struct {
Path string `json:"path,omitempty" yaml:"path,omitempty"`
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
YAMLSupport bool `json:"yamlSupport,omitempty" yaml:"yamlSupport,omitempty"`
}
func (p *PatchTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
err = yaml.Unmarshal(c, p)
h *resmap.PluginHelpers, c []byte) error {
err := yaml.Unmarshal(c, p)
if err != nil {
return err
}
p.Patch = strings.TrimSpace(p.Patch)
if p.Patch == "" && p.Path == "" {
err = fmt.Errorf(
return fmt.Errorf(
"must specify one of patch and path in\n%s", string(c))
return
}
if p.Patch != "" && p.Path != "" {
err = fmt.Errorf(
return fmt.Errorf(
"patch and path can't be set at the same time\n%s", string(c))
return
}
var in []byte
if p.Path != "" {
in, err = h.Loader().Load(p.Path)
if err != nil {
return
}
}
if p.Patch != "" {
in = []byte(p.Patch)
}
patchSM, errSM := h.ResmapFactory().RF().FromBytes(in)
patchJson, errJson := jsonPatchFromBytes(in)
if p.Path != "" {
loaded, loadErr := h.Loader().Load(p.Path)
if loadErr != nil {
return loadErr
}
p.Patch = string(loaded)
}
patchSM, errSM := h.ResmapFactory().RF().FromBytes([]byte(p.Patch))
patchJson, errJson := jsonPatchFromBytes([]byte(p.Patch))
if (errSM == nil && errJson == nil) ||
(patchSM != nil && patchJson != nil) {
return fmt.Errorf(
"illegally qualifies as both an SM and JSON patch: [%v]",
p.Patch)
}
if errSM != nil && errJson != nil {
err = fmt.Errorf(
"unable to get either a Strategic Merge Patch or JSON patch 6902 from %s", p.Patch)
return
return fmt.Errorf(
"unable to parse SM or JSON patch from [%v]", p.Patch)
}
if errSM == nil && errJson != nil {
if errSM == nil {
p.loadedPatch = patchSM
}
if errJson == nil && errSM != nil {
} else {
p.decodedPatch = patchJson
}
if patchSM != nil && patchJson != nil {
err = fmt.Errorf(
"a patch can't be both a Strategic Merge Patch and JSON patch 6902 %s", p.Patch)
}
return nil
}
func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
if p.loadedPatch != nil && p.Target == nil {
target, err := m.GetById(p.loadedPatch.OrgId())
if p.loadedPatch != nil {
// The patch was a strategic merge patch
return p.transformStrategicMerge(m, p.loadedPatch)
} else {
return p.transformJson6902(m, p.decodedPatch)
}
}
// transformStrategicMerge applies the provided strategic merge patch
// to all the resources in the ResMap that match either the Target or
// the identifier of the patch.
func (p *PatchTransformerPlugin) transformStrategicMerge(m resmap.ResMap, patch *resource.Resource) error {
if p.Target == nil {
target, err := m.GetById(patch.OrgId())
if err != nil {
return err
}
err = target.Patch(p.loadedPatch.Kunstructured)
if err != nil {
return err
}
return nil
return p.applySMPatch(target, patch)
}
resources, err := m.Select(*p.Target)
if err != nil {
return err
}
for _, res := range resources {
patchCopy := patch.DeepCopy()
patchCopy.SetName(res.GetName())
patchCopy.SetNamespace(res.GetNamespace())
patchCopy.SetGvk(res.GetGvk())
err := p.applySMPatch(res, patchCopy)
if err != nil {
return err
}
}
return nil
}
// applySMPatch applies the provided strategic merge patch to the
// given resource. Depending on the value of YAMLSupport, it will either
// use the legacy implementation or the kyaml-based solution.
func (p *PatchTransformerPlugin) applySMPatch(resource, patch *resource.Resource) error {
if !p.YAMLSupport {
return resource.Patch(patch.Kunstructured)
} else {
node, err := filtersutil.GetRNode(patch)
if err != nil {
return err
}
return filtersutil.ApplyToJSON(patchstrategicmerge.Filter{
Patch: node,
}, resource.Kunstructured)
}
}
// transformJson6902 applies the provided json6902 patch
// to all the resources in the ResMap that match the Target.
func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpatch.Patch) error {
if p.Target == nil {
return fmt.Errorf("must specify a target for patch %s", p.Patch)
}
@@ -92,35 +139,36 @@ func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
return err
}
for _, res := range resources {
if p.decodedPatch != nil {
rawObj, err := res.MarshalJSON()
if err != nil {
return err
}
modifiedObj, err := p.decodedPatch.Apply(rawObj)
if err != nil {
return errors.Wrapf(
err, "failed to apply json patch '%s'", p.Patch)
}
err = res.UnmarshalJSON(modifiedObj)
if err != nil {
return err
}
}
if p.loadedPatch != nil {
patchCopy := p.loadedPatch.DeepCopy()
patchCopy.SetName(res.GetName())
patchCopy.SetNamespace(res.GetNamespace())
patchCopy.SetGvk(res.GetGvk())
err = res.Patch(patchCopy.Kunstructured)
if err != nil {
return err
}
err = p.applyJson6902Patch(res, patch)
if err != nil {
return err
}
}
return nil
}
// applyJson6902Patch applies the provided patch to the given resource.
// Depending on the value of YAMLSupport, it will either
// use the legacy implementation or the kyaml-based solution.
func (p *PatchTransformerPlugin) applyJson6902Patch(resource *resource.Resource, patch jsonpatch.Patch) error {
if !p.YAMLSupport {
rawObj, err := resource.MarshalJSON()
if err != nil {
return err
}
modifiedObj, err := patch.Apply(rawObj)
if err != nil {
return errors.Wrapf(
err, "failed to apply json patch '%s'", p.Patch)
}
return resource.UnmarshalJSON(modifiedObj)
} else {
return filtersutil.ApplyToJSON(patchjson6902.Filter{
Patch: p.Patch,
}, resource.Kunstructured)
}
}
// jsonPatchFromBytes loads a Json 6902 patch from
// a bytes input
func jsonPatchFromBytes(

View File

@@ -13,12 +13,10 @@ import (
type SecretGeneratorPlugin struct {
h *resmap.PluginHelpers
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
types.GeneratorOptions
types.SecretArgs
}
func (p *SecretGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
p.GeneratorOptions = types.GeneratorOptions{}
p.SecretArgs = types.SecretArgs{}
err = yaml.Unmarshal(config, p)
if p.SecretArgs.Name == "" {
@@ -33,8 +31,7 @@ func (p *SecretGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (
func (p *SecretGeneratorPlugin) Generate() (resmap.ResMap, error) {
return p.h.ResmapFactory().FromSecretArgs(
kv.NewLoader(p.h.Loader(), p.h.Validator()),
&p.GeneratorOptions, p.SecretArgs)
kv.NewLoader(p.h.Loader(), p.h.Validator()), p.SecretArgs)
}
func NewSecretGeneratorPlugin() resmap.GeneratorPlugin {

View File

@@ -0,0 +1,142 @@
// Code generated by pluginator on ValueAddTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"path/filepath"
"strings"
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/filters/valueadd"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml"
)
// An 'Add' transformer inspired by the IETF RFC 6902 JSON spec Add operation.
type ValueAddTransformerPlugin struct {
// Value is the value to add.
// Defaults to base name of encompassing kustomization root.
Value string `json:"value,omitempty" yaml:"value,omitempty"`
// Targets is a slice of targets that should have the value added.
Targets []Target `json:"targets,omitempty" yaml:"targets,omitempty"`
// TargetFilePath is a file path. If specified, the file will be parsed into
// a slice of Target, and appended to anything that was specified in the
// Targets field. This is just a means to share common target specifications.
TargetFilePath string `json:"targetFilePath,omitempty" yaml:"targetFilePath,omitempty"`
}
// Target describes where to put the value.
type Target struct {
// Selector selects the resources to modify.
Selector *types.Selector `json:"selector,omitempty" yaml:"selector,omitempty"`
// NotSelector selects the resources to exclude
// from those included by overly broad selectors.
// TODO: implement this?
// NotSelector *types.Selector `json:"notSelector,omitempty" yaml:"notSelector,omitempty"`
// FieldPath is a JSON-style path to the field intended to hold the value.
FieldPath string `json:"fieldPath,omitempty" yaml:"fieldPath,omitempty"`
// FilePathPosition is passed to the filter directly. Look there for doc.
FilePathPosition int `json:"filePathPosition,omitempty" yaml:"filePathPosition,omitempty"`
}
func (p *ValueAddTransformerPlugin) Config(h *resmap.PluginHelpers, c []byte) error {
err := yaml.Unmarshal(c, p)
if err != nil {
return err
}
p.Value = strings.TrimSpace(p.Value)
if p.Value == "" {
p.Value = filepath.Base(h.Loader().Root())
}
if p.TargetFilePath != "" {
bytes, err := h.Loader().Load(p.TargetFilePath)
if err != nil {
return err
}
var targets struct {
Targets []Target `json:"targets,omitempty" yaml:"targets,omitempty"`
}
err = yaml.Unmarshal(bytes, &targets)
if err != nil {
return err
}
p.Targets = append(p.Targets, targets.Targets...)
}
if len(p.Targets) == 0 {
return fmt.Errorf("must specify at least one target")
}
for _, target := range p.Targets {
if err = validateSelector(target.Selector); err != nil {
return err
}
// TODO: call validateSelector(target.NotSelector) if field added.
if err = validateJsonFieldPath(target.FieldPath); err != nil {
return err
}
if target.FilePathPosition < 0 {
return fmt.Errorf(
"value of FilePathPosition (%d) cannot be negative",
target.FilePathPosition)
}
}
return nil
}
// TODO: implement
func validateSelector(_ *types.Selector) error {
return nil
}
// TODO: Enforce RFC 6902?
func validateJsonFieldPath(p string) error {
if len(p) == 0 {
return fmt.Errorf("fieldPath cannot be empty")
}
return nil
}
func (p *ValueAddTransformerPlugin) Transform(m resmap.ResMap) (err error) {
for _, t := range p.Targets {
var resources []*resource.Resource
if t.Selector == nil {
resources = m.Resources()
} else {
resources, err = m.Select(*t.Selector)
if err != nil {
return err
}
}
// TODO: consider t.NotSelector if implemented
for _, res := range resources {
if t.FieldPath == types.MetadataNamespacePath {
err = filtersutil.ApplyToJSON(namespace.Filter{
Namespace: p.Value,
}, res.Kunstructured)
} else {
err = filtersutil.ApplyToJSON(valueadd.Filter{
Value: p.Value,
FieldPath: t.FieldPath,
FilePathPosition: t.FilePathPosition,
}, res.Kunstructured)
}
if err != nil {
return err
}
}
}
return nil
}
func NewValueAddTransformerPlugin() resmap.TransformerPlugin {
return &ValueAddTransformerPlugin{}
}

View File

@@ -3,7 +3,11 @@
package filesys
import "path/filepath"
import (
"os"
"path/filepath"
"strings"
)
// RootedPath returns a rooted path, e.g. "/foo/bar" as
// opposed to "foo/bar".
@@ -28,3 +32,94 @@ func StripLeadingSeps(s string) string {
}
return s[k:]
}
// PathSplit converts a file path to a slice of string.
// If the path is absolute (if the path has a leading slash),
// then the first entry in the result is an empty string.
// Desired: path == PathJoin(PathSplit(path))
func PathSplit(incoming string) []string {
if incoming == "" {
return []string{}
}
dir, path := filepath.Split(incoming)
if dir == string(os.PathSeparator) {
if path == "" {
return []string{""}
}
return []string{"", path}
}
dir = strings.TrimSuffix(dir, string(os.PathSeparator))
if dir == "" {
return []string{path}
}
return append(PathSplit(dir), path)
}
// PathJoin converts a slice of string to a file path.
// If the first entry is an empty string, then the returned
// path is absolute (it has a leading slash).
// Desired: path == PathJoin(PathSplit(path))
func PathJoin(incoming []string) string {
if len(incoming) == 0 {
return ""
}
if incoming[0] == "" {
return string(os.PathSeparator) + filepath.Join(incoming[1:]...)
}
return filepath.Join(incoming...)
}
// InsertPathPart inserts 'part' at position 'pos' in the given filepath.
// The first position is 0.
//
// E.g. if part == 'PEACH'
//
// OLD : NEW : POS
// --------------------------------------------------------
// {empty} : PEACH : irrelevant
// / : /PEACH : irrelevant
// pie : PEACH/pie : 0 (or negative)
// /pie : /PEACH/pie : 0 (or negative)
// raw : raw/PEACH : 1 (or larger)
// /raw : /raw/PEACH : 1 (or larger)
// a/nice/warm/pie : a/nice/warm/PEACH/pie : 3
// /a/nice/warm/pie : /a/nice/warm/PEACH/pie : 3
//
// * An empty part results in no change.
//
// * Absolute paths get their leading '/' stripped, treated like
// relative paths, and the leading '/' is re-added on output.
// The meaning of pos is intentionally the same in either absolute or
// relative paths; if it weren't, this function could convert absolute
// paths to relative paths, which is not desirable.
//
// * For robustness (liberal input, conservative output) Pos values that
// that are too small (large) to index the split filepath result in a
// prefix (postfix) rather than an error. Use extreme position values
// to assure a prefix or postfix (e.g. 0 will always prefix, and
// 9999 will presumably always postfix).
func InsertPathPart(path string, pos int, part string) string {
if part == "" {
return path
}
parts := PathSplit(path)
if pos < 0 {
pos = 0
} else if pos > len(parts) {
pos = len(parts)
}
if len(parts) > 0 && parts[0] == "" && pos < len(parts) {
// An empty string at 0 indicates an absolute path, and means
// we must increment pos. This change means that a position
// specification has the same meaning in relative and absolute paths.
// E.g. in either the path 'a/b/c' or the path '/a/b/c',
// 'a' is at 0, 'b' is at 1 and 'c' is at 2, and inserting at
// zero means a new first field _without_ changing an absolute
// path to a relative path.
pos++
}
result := make([]string, len(parts)+1)
copy(result, parts[0:pos])
result[pos] = part
return PathJoin(append(result, parts[pos:]...))
}

View File

@@ -1,6 +1,7 @@
package filesys_test
import (
"os"
"path/filepath"
"testing"
@@ -93,6 +94,11 @@ func TestFilePathSplit(t *testing.T) {
dir: "",
file: "rabbit.jpg",
},
{
full: "/",
dir: "/",
file: "",
},
{
full: "/beans",
dir: "/",
@@ -124,6 +130,169 @@ func TestFilePathSplit(t *testing.T) {
}
}
func TestPathSplitAndJoin(t *testing.T) {
cases := map[string]struct {
original string
expected []string
}{
"Empty": {
original: "",
expected: []string{},
},
"One": {
original: "hello",
expected: []string{"hello"},
},
"Two": {
original: "hello/there",
expected: []string{"hello", "there"},
},
"Three": {
original: "hello/my/friend",
expected: []string{"hello", "my", "friend"},
},
}
for n, c := range cases {
f := func(t *testing.T, original string, expected []string) {
actual := PathSplit(original)
if len(actual) != len(expected) {
t.Fatalf(
"expected len %d, got len %d",
len(expected), len(actual))
}
for i := range expected {
if expected[i] != actual[i] {
t.Fatalf(
"at i=%d, expected '%s', got '%s'",
i, expected[i], actual[i])
}
}
joined := PathJoin(actual)
if joined != original {
t.Fatalf(
"when rejoining, expected '%s', got '%s'",
original, joined)
}
}
t.Run("relative"+n, func(t *testing.T) {
f(t, c.original, c.expected)
})
t.Run("absolute"+n, func(t *testing.T) {
f(t,
string(os.PathSeparator)+c.original,
append([]string{""}, c.expected...))
})
}
}
func TestInsertPathPart(t *testing.T) {
cases := map[string]struct {
original string
pos int
part string
expected string
}{
"rootOne": {
original: "/",
pos: 0,
part: "___",
expected: "/___",
},
"rootTwo": {
original: "/",
pos: 444,
part: "___",
expected: "/___",
},
"rootedFirst": {
original: "/apple",
pos: 0,
part: "___",
expected: "/___/apple",
},
"rootedSecond": {
original: "/apple",
pos: 444,
part: "___",
expected: "/apple/___",
},
"rootedThird": {
original: "/apple/banana",
pos: 444,
part: "___",
expected: "/apple/banana/___",
},
"emptyLow": {
original: "",
pos: -3,
part: "___",
expected: "___",
},
"emptyHigh": {
original: "",
pos: 444,
part: "___",
expected: "___",
},
"peachPie": {
original: "a/nice/warm/pie",
pos: 3,
part: "PEACH",
expected: "a/nice/warm/PEACH/pie",
},
"rootedPeachPie": {
original: "/a/nice/warm/pie",
pos: 3,
part: "PEACH",
expected: "/a/nice/warm/PEACH/pie",
},
"longStart": {
original: "a/b/c/d/e/f",
pos: 0,
part: "___",
expected: "___/a/b/c/d/e/f",
},
"rootedLongStart": {
original: "/a/b/c/d/e/f",
pos: 0,
part: "___",
expected: "/___/a/b/c/d/e/f",
},
"longMiddle": {
original: "a/b/c/d/e/f",
pos: 3,
part: "___",
expected: "a/b/c/___/d/e/f",
},
"rootedLongMiddle": {
original: "/a/b/c/d/e/f",
pos: 3,
part: "___",
expected: "/a/b/c/___/d/e/f",
},
"longEnd": {
original: "a/b/c/d/e/f",
pos: 444,
part: "___",
expected: "a/b/c/d/e/f/___",
},
"rootedLongEnd": {
original: "/a/b/c/d/e/f",
pos: 444,
part: "___",
expected: "/a/b/c/d/e/f/___",
},
}
for n, c := range cases {
t.Run(n, func(t *testing.T) {
actual := InsertPathPart(c.original, c.pos, c.part)
if actual != c.expected {
t.Fatalf("expected '%s', got '%s'", c.expected, actual)
}
})
}
}
func TestStripTrailingSeps(t *testing.T) {
cases := []struct {
full string

View File

@@ -124,12 +124,7 @@ func isMatchGVK(fs types.FieldSpec, obj *yaml.RNode) (bool, error) {
}
// parse the group and version from the apiVersion field
var group, version string
parts := strings.SplitN(meta.APIVersion, "/", 2)
group = parts[0]
if len(parts) > 1 {
version = parts[1]
}
group, version := parseGV(meta.APIVersion)
if fs.Group != "" && fs.Group != group {
// group doesn't match

View File

@@ -4,9 +4,6 @@
package fsslice
import (
"strings"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
@@ -59,20 +56,3 @@ func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
}
return obj, nil
}
// GetGVK parses the metadata into a GVK
func GetGVK(meta yaml.ResourceMeta) resid.Gvk {
// parse the group and version from the apiVersion field
var group, version string
parts := strings.SplitN(meta.APIVersion, "/", 2)
group = parts[0]
if len(parts) > 1 {
version = parts[1]
}
return resid.Gvk{
Group: group,
Version: version,
Kind: meta.Kind,
}
}

View File

@@ -10,7 +10,6 @@ import (
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/filters/fsslice"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
@@ -281,6 +280,52 @@ kind: Bar
a:
b:
- c: {d: e}
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
{
name: "group v1",
fsSlice: `
- path: a/b
group: v1
create: true
kind: Bar
`,
input: `
apiVersion: v1
kind: Bar
`,
expected: `
apiVersion: v1
kind: Bar
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
CreateKind: yaml.ScalarNode,
},
},
{
name: "version v1",
fsSlice: `
- path: a/b
version: v1
create: true
kind: Bar
`,
input: `
apiVersion: v1
kind: Bar
`,
expected: `
apiVersion: v1
kind: Bar
a:
b: e
`,
filter: fsslice.Filter{
SetValue: fsslice.SetScalar("e"),
@@ -332,23 +377,3 @@ func TestFilter_Filter(t *testing.T) {
})
}
}
func TestGetGVK(t *testing.T) {
obj, err := yaml.Parse(`
apiVersion: apps/v1
kind: Deployment
`)
if !assert.NoError(t, err) {
t.FailNow()
}
meta, err := obj.GetMeta()
if !assert.NoError(t, err) {
t.FailNow()
}
gvk := fsslice.GetGVK(meta)
expected := resid.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
if !assert.Equal(t, expected, gvk) {
t.FailNow()
}
}

View File

@@ -0,0 +1,49 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package fsslice
import (
"strings"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Return true for 'v' followed by a 1 or 2, and don't look at rest.
// I.e. 'v1', 'v1beta1', 'v2', would return true.
func looksLikeACoreApiVersion(s string) bool {
if len(s) < 2 {
return false
}
if s[0:1] != "v" {
return false
}
return s[1:2] == "1" || s[1:2] == "2"
}
// parseGV parses apiVersion field into group and version.
func parseGV(apiVersion string) (group, version string) {
// parse the group and version from the apiVersion field
parts := strings.SplitN(apiVersion, "/", 2)
group = parts[0]
if len(parts) > 1 {
version = parts[1]
}
// Special case the original "apiVersion" of what
// we now call the "core" (empty) group.
if version == "" && looksLikeACoreApiVersion(group) {
version = group
group = ""
}
return
}
// GetGVK parses the metadata into a GVK
func GetGVK(meta yaml.ResourceMeta) resid.Gvk {
group, version := parseGV(meta.APIVersion)
return resid.Gvk{
Group: group,
Version: version,
Kind: meta.Kind,
}
}

View File

@@ -0,0 +1,156 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package fsslice
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func TestParseGV(t *testing.T) {
testCases := map[string]struct {
input string
expectedGroup string
expectedVersion string
}{
"empty": {
input: "",
expectedGroup: "",
expectedVersion: "",
},
"certSigning": {
input: "certificates.k8s.io/v1beta1",
expectedGroup: "certificates.k8s.io",
expectedVersion: "v1beta1",
},
"extensions": {
input: "extensions/v1beta1",
expectedGroup: "extensions",
expectedVersion: "v1beta1",
},
"normal": {
input: "apps/v1",
expectedGroup: "apps",
expectedVersion: "v1",
},
"justApps": {
input: "apps",
expectedGroup: "apps",
expectedVersion: "",
},
"coreV1": {
input: "v1",
expectedGroup: "",
expectedVersion: "v1",
},
"coreV2": {
input: "v2",
expectedGroup: "",
expectedVersion: "v2",
},
"coreV2Beta1": {
input: "v2beta1",
expectedGroup: "",
expectedVersion: "v2beta1",
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
group, version := parseGV(tc.input)
if !assert.Equal(t, tc.expectedGroup, group) {
t.FailNow()
}
if !assert.Equal(t, tc.expectedVersion, version) {
t.FailNow()
}
})
}
}
func TestGetGVK(t *testing.T) {
testCases := map[string]struct {
input string
expected resid.Gvk
parseError string
metaError string
}{
"empty": {
input: `
`,
parseError: "EOF",
},
"junk": {
input: `
congress: effective
`,
metaError: "missing Resource metadata",
},
"normal": {
input: `
apiVersion: apps/v1
kind: Deployment
`,
expected: resid.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"},
},
"apiVersionOnlyWithSlash": {
input: `
apiVersion: apps/v1
`,
expected: resid.Gvk{Group: "apps", Version: "v1", Kind: ""},
},
"apiVersionOnlyNoSlash1": {
input: `
apiVersion: apps
`,
expected: resid.Gvk{Group: "apps", Version: "", Kind: ""},
},
"apiVersionOnlyNoSlash2": {
input: `
apiVersion: v1
`,
expected: resid.Gvk{Group: "", Version: "v1", Kind: ""},
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
obj, err := yaml.Parse(tc.input)
if len(tc.parseError) != 0 {
if err == nil {
t.Error("expected parse error")
return
}
if !strings.Contains(err.Error(), tc.parseError) {
t.Errorf("expected parse err '%s', got '%v'", tc.parseError, err)
}
return
}
if !assert.NoError(t, err) {
t.FailNow()
}
meta, err := obj.GetMeta()
if len(tc.metaError) != 0 {
if err == nil {
t.Error("expected meta error")
return
}
if !strings.Contains(err.Error(), tc.metaError) {
t.Errorf("expected meta err '%s', got '%v'", tc.metaError, err)
}
return
}
if !assert.NoError(t, err) {
t.FailNow()
}
gvk := GetGVK(meta)
if !assert.Equal(t, tc.expected, gvk) {
t.FailNow()
}
})
}
}

View File

@@ -8,19 +8,16 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/resid"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
"sigs.k8s.io/kustomize/api/types"
)
var labelsFs = builtinconfig.MakeDefaultConfig().CommonLabels
func TestLabels_Filter(t *testing.T) {
testCases := map[string]struct {
input string
expectedOutput string
filter Filter
fsSlice types.FsSlice
}{
"add": {
input: `
@@ -45,12 +42,20 @@ metadata:
clown: emmett kelley
dragon: smaug
`,
filter: Filter{Labels: labelMap{
"clown": "emmett kelley",
"auto": "ford",
"dragon": "smaug",
"bean": "cannellini",
}},
filter: Filter{
Labels: labelMap{
"clown": "emmett kelley",
"auto": "ford",
"dragon": "smaug",
"bean": "cannellini",
},
FsSlice: []types.FieldSpec{
{
Path: "metadata/labels",
CreateIfNotPresent: true,
},
},
},
},
"update": {
input: `
@@ -73,13 +78,21 @@ metadata:
bean: cannellini
clown: emmett kelley
`,
filter: Filter{Labels: labelMap{
"clown": "emmett kelley",
"hero": "superman",
"fiend": "luthor",
"bean": "cannellini",
}},
filter: Filter{
Labels: labelMap{
"clown": "emmett kelley",
"hero": "superman",
"fiend": "luthor",
"bean": "cannellini",
}, FsSlice: []types.FieldSpec{
{
Path: "metadata/labels",
CreateIfNotPresent: true,
},
},
},
},
"data-fieldspecs": {
input: `
apiVersion: example.com/v1
@@ -113,13 +126,168 @@ a:
b:
sleater: kinney
`,
filter: Filter{Labels: labelMap{
"sleater": "kinney",
}},
fsSlice: []types.FieldSpec{
{
Path: "a/b",
CreateIfNotPresent: true,
filter: Filter{
Labels: labelMap{
"sleater": "kinney",
},
FsSlice: []types.FieldSpec{
{
Path: "metadata/labels",
CreateIfNotPresent: true,
},
{
Path: "a/b",
CreateIfNotPresent: true,
},
},
},
},
"fieldSpecWithKind": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v2
kind: Bar
metadata:
name: instance
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
labels:
cheese: cheddar
---
apiVersion: example.com/v2
kind: Bar
metadata:
name: instance
labels:
cheese: cheddar
a:
b:
cheese: cheddar
`,
filter: Filter{
Labels: labelMap{
"cheese": "cheddar",
},
FsSlice: []types.FieldSpec{
{
Path: "metadata/labels",
CreateIfNotPresent: true,
},
{
Gvk: resid.Gvk{
Kind: "Bar",
},
Path: "a/b",
CreateIfNotPresent: true,
},
},
},
},
"fieldSpecWithVersion": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
---
apiVersion: example.com/v2
kind: Bar
metadata:
name: instance
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
labels:
cheese: cheddar
a:
b:
cheese: cheddar
---
apiVersion: example.com/v2
kind: Bar
metadata:
name: instance
labels:
cheese: cheddar
`,
filter: Filter{
Labels: labelMap{
"cheese": "cheddar",
},
FsSlice: []types.FieldSpec{
{
Path: "metadata/labels",
CreateIfNotPresent: true,
},
{
Gvk: resid.Gvk{
Version: "v1",
},
Path: "a/b",
CreateIfNotPresent: true,
},
},
},
},
"fieldSpecWithVersionInConfigButNoGroupInData": {
input: `
apiVersion: v1
kind: Foo
metadata:
name: instance
---
apiVersion: v2
kind: Bar
metadata:
name: instance
`,
expectedOutput: `
apiVersion: v1
kind: Foo
metadata:
name: instance
labels:
cheese: cheddar
a:
b:
cheese: cheddar
---
apiVersion: v2
kind: Bar
metadata:
name: instance
labels:
cheese: cheddar
`,
filter: Filter{
Labels: labelMap{
"cheese": "cheddar",
},
FsSlice: []types.FieldSpec{
{
Path: "metadata/labels",
CreateIfNotPresent: true,
},
{
Gvk: resid.Gvk{
Version: "v1",
},
Path: "a/b",
CreateIfNotPresent: true,
},
},
},
},
@@ -127,11 +295,9 @@ a:
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
filter := tc.filter
filter.FsSlice = append(labelsFs, tc.fsSlice...)
if !assert.Equal(t,
strings.TrimSpace(tc.expectedOutput),
strings.TrimSpace(filtertest_test.RunFilter(t, tc.input, filter))) {
strings.TrimSpace(filtertest_test.RunFilter(t, tc.input, tc.filter))) {
t.FailNow()
}
})

View File

@@ -78,7 +78,7 @@ func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) erro
}
f := fsslice.Filter{
FsSlice: []types.FieldSpec{
{Path: metaNamespaceField, CreateIfNotPresent: true},
{Path: types.MetadataNamespacePath, CreateIfNotPresent: true},
},
SetValue: fsslice.SetScalar(ns.Namespace),
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
@@ -143,7 +143,7 @@ func (ns Filter) removeFieldSpecsForHacks(fs types.FsSlice) types.FsSlice {
var val types.FsSlice
for i := range fs {
// implemented by metaNamespaceHack
if fs[i].Path == metaNamespaceField {
if fs[i].Path == types.MetadataNamespacePath {
continue
}
// implemented by roleBindingHack
@@ -160,7 +160,6 @@ func (ns Filter) removeFieldSpecsForHacks(fs types.FsSlice) types.FsSlice {
}
const (
metaNamespaceField = "metadata/namespace"
subjectsField = "subjects"
roleBindingKind = "RoleBinding"
clusterRoleBindingKind = "ClusterRoleBinding"

View File

@@ -0,0 +1,124 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package valueadd
import (
"strings"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// An 'Add' operation aspiring to IETF RFC 6902 JSON.
//
// The filter tries to add a value to a node at a particular field path.
//
// Kinds of target fields:
//
// - Non-existent target field.
//
// The field will be added and the value inserted.
//
// - Existing field, scalar or map.
//
// E.g. 'spec/template/spec/containers/[name:nginx]/image'
//
// This behaves like an IETF RFC 6902 Replace operation would;
// the existing value is replaced without complaint, even though
// this is an Add operation. In contrast, a Replace operation
// must fail (report an error) if the field doesn't exist.
//
// - Existing field, list (array)
// Not supported yet.
// TODO: Honor fields with RFC-6902-style array indices
// TODO: like 'spec/template/spec/containers/2'
// TODO: Modify kyaml/yaml/PathGetter to allow this.
// The value will be inserted into the array at the given position,
// shifting other contents. To instead replace an array entry, use
// an implementation of an IETF RFC 6902 Replace operation.
//
// For the common case of a filepath in the field value, and a desire
// to add the value to the filepath (rather than replace the filepath),
// use a non-zero value of FilePathPosition (see below).
type Filter struct {
// Value is the value to add.
//
// Empty values are disallowed, i.e. this filter isn't intended
// for use in erasing or removing fields. For that, use a filter
// more aligned with the IETF RFC 6902 JSON Remove operation.
//
// At the time of writing, Value's value should be a simple string,
// not a JSON document. This particular filter focuses on easing
// injection of a single-sourced cloud project and/or cluster name
// into various fields, especially namespace and various filepath
// specifications.
Value string
// FieldPath is a JSON-style path to the field intended to hold the value.
FieldPath string
// FilePathPosition is a filepath field index.
//
// Call the value of this field _i_.
//
// If _i_ is zero, negative or unspecified, this field has no effect.
//
// If _i_ is > 0, then it's assumed that
// - 'Value' is a string that can work as a directory or file name,
// - the field value intended for replacement holds a filepath.
//
// The filepath is split into a string slice, the value is inserted
// at position [i-1], shifting the rest of the path to the right.
// A value of i==1 puts the new value at the start of the path.
// This change never converts an absolute path to a relative path,
// meaning adding a new field at position i==1 will preserve a
// leading slash. E.g. if Value == 'PEACH'
//
// OLD : NEW : FilePathPosition
// --------------------------------------------------------
// {empty} : PEACH : irrelevant
// / : /PEACH : irrelevant
// pie : PEACH/pie : 1 (or less to prefix)
// /pie : /PEACH/pie : 1 (or less to prefix)
// raw : raw/PEACH : 2 (or more to postfix)
// /raw : /raw/PEACH : 2 (or more to postfix)
// a/nice/warm/pie : a/nice/warm/PEACH/pie : 4
// /a/nice/warm/pie : /a/nice/warm/PEACH/pie : 4
//
// For robustness (liberal input, conservative output) FilePathPosition
// values that that are too large to index the split filepath result in a
// postfix rather than an error. So use 1 to prefix, 9999 to postfix.
FilePathPosition int `json:"filePathPosition,omitempty" yaml:"filePathPosition,omitempty"`
}
var _ kio.Filter = Filter{}
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
_, err := kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
fields := strings.Split(f.FieldPath, "/")
// TODO: support SequenceNode.
// Presumably here one could look for array indices (digits) at
// the end of the field path (as described in IETF RFC 6902 JSON),
// and if found, take it as a signal that this should be a
// SequenceNode instead of a ScalarNode, and insert the value
// into the proper slot, shifting every over.
n, err := node.Pipe(yaml.LookupCreate(yaml.ScalarNode, fields...))
if err != nil {
return node, err
}
// TODO: allow more kinds
if err := yaml.ErrorIfInvalid(n, yaml.ScalarNode); err != nil {
return nil, err
}
newValue := f.Value
if f.FilePathPosition > 0 {
newValue = filesys.InsertPathPart(
n.YNode().Value, f.FilePathPosition-1, newValue)
}
return n.Pipe(yaml.FieldSetter{StringValue: newValue})
})).Filter(nodes)
return nodes, err
}

View File

@@ -0,0 +1,109 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package valueadd
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
)
const someResource = `
kind: SomeKind
spec:
resourceRef:
external: projects/whatever
`
func TestValueAddFilter(t *testing.T) {
testCases := map[string]struct {
input string
expectedOutput string
filter Filter
}{
"simpleAdd": {
input: `
kind: SomeKind
`,
expectedOutput: `
kind: SomeKind
spec:
resourceRef:
external: valueAdded
`,
filter: Filter{
Value: "valueAdded",
FieldPath: "spec/resourceRef/external",
},
},
"replaceExisting": {
input: someResource,
expectedOutput: `
kind: SomeKind
spec:
resourceRef:
external: valueAdded
`,
filter: Filter{
Value: "valueAdded",
FieldPath: "spec/resourceRef/external",
},
},
"prefixExisting": {
input: someResource,
expectedOutput: `
kind: SomeKind
spec:
resourceRef:
external: valueAdded/projects/whatever
`,
filter: Filter{
Value: "valueAdded",
FieldPath: "spec/resourceRef/external",
FilePathPosition: 1,
},
},
"postfixExisting": {
input: someResource,
expectedOutput: `
kind: SomeKind
spec:
resourceRef:
external: projects/whatever/valueAdded
`,
filter: Filter{
Value: "valueAdded",
FieldPath: "spec/resourceRef/external",
FilePathPosition: 99,
},
},
"placeInMiddleOfExisting": {
input: someResource,
expectedOutput: `
kind: SomeKind
spec:
resourceRef:
external: projects/valueAdded/whatever
`,
filter: Filter{
Value: "valueAdded",
FieldPath: "spec/resourceRef/external",
FilePathPosition: 2,
},
},
}
for tn, tc := range testCases {
t.Run(tn, func(t *testing.T) {
filter := tc.filter
if !assert.Equal(t,
strings.TrimSpace(tc.expectedOutput),
strings.TrimSpace(filtertest_test.RunFilter(t, tc.input, filter))) {
t.FailNow()
}
})
}
}

View File

@@ -11,11 +11,11 @@ require (
github.com/stretchr/testify v1.4.0
github.com/yujunz/go-getter v1.4.1-lite
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff
gopkg.in/yaml.v2 v2.2.7
gopkg.in/yaml.v2 v2.2.8
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0
k8s.io/client-go v0.17.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
sigs.k8s.io/kustomize/kyaml v0.1.5
sigs.k8s.io/yaml v1.1.0
sigs.k8s.io/kustomize/kyaml v0.1.10
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -45,6 +45,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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=
@@ -295,8 +296,10 @@ github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d h1:BzRvVq1EHuIjxpijCEKpAxzKUUMurOQ4sknehIATRh8=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
@@ -304,6 +307,7 @@ github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -318,6 +322,8 @@ github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
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=
@@ -399,6 +405,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/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/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/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/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -422,6 +430,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c h1:Vco5b+cuG5NNfORVxZy6bYZQ7rsigisU1WQFkvQ0L5E=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/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=
@@ -480,6 +489,8 @@ 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.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/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=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -506,17 +517,12 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphD
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize v1.0.11 h1:Yb+6DDt9+aR2AvQApvUaKS/ugteeG4MPyoFeUHiPOjk=
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
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/kustomize/kyaml v0.1.2 h1:l12+QGl+ETUHhP8/bZAi6TknU7H194fXL/9b2gUxZFY=
sigs.k8s.io/kustomize/kyaml v0.1.3 h1:zbeHVTMCQPtWgjIH/YYJZC45mm7coTdw2TblyJ79BrY=
sigs.k8s.io/kustomize/kyaml v0.1.3/go.mod h1:461i94nj0h0ylJ6w83jLkR4SqqVhn1iY6fjD0JSTQeE=
sigs.k8s.io/kustomize/kyaml v0.1.5 h1:NicBWYTwkuOfVyZDbNkfSBSCwSgin4uirkedtyZltIc=
sigs.k8s.io/kustomize/kyaml v0.1.5/go.mod h1:461i94nj0h0ylJ6w83jLkR4SqqVhn1iY6fjD0JSTQeE=
sigs.k8s.io/kustomize/kyaml v0.1.10 h1:ZZfBnA/kYa9ZxUFIgI9oq3pWKzzA1gGOKgU0Hv/NhVg=
sigs.k8s.io/kustomize/kyaml v0.1.10/go.mod h1:mPmeBSRy0LTMv6fSrYSoi2yIFNZVouGKDsTekE5kdhs=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

View File

@@ -75,14 +75,8 @@ type KunstructuredFactory interface {
SliceFromBytes([]byte) ([]Kunstructured, error)
FromMap(m map[string]interface{}) Kunstructured
Hasher() KunstructuredHasher
MakeConfigMap(
kvLdr KvLoader,
options *types.GeneratorOptions,
args *types.ConfigMapArgs) (Kunstructured, error)
MakeSecret(
kvLdr KvLoader,
options *types.GeneratorOptions,
args *types.SecretArgs) (Kunstructured, error)
MakeConfigMap(kvLdr KvLoader, args *types.ConfigMapArgs) (Kunstructured, error)
MakeSecret(kvLdr KvLoader, args *types.SecretArgs) (Kunstructured, error)
}
// KunstructuredHasher returns a hash of the argument

View File

@@ -40,7 +40,11 @@ func (rv *refVarTransformer) replaceVars(in interface{}) (interface{}, error) {
case []interface{}:
var xs []interface{}
for _, a := range in.([]interface{}) {
xs = append(xs, expansion2.Expand(a.(string), rv.mappingFunc))
x, ok := a.(string)
if !ok {
return nil, fmt.Errorf("expected array of strings, found %v", in)
}
xs = append(xs, expansion2.Expand(x, rv.mappingFunc))
}
return xs, nil
case map[string]interface{}:
@@ -49,7 +53,7 @@ func (rv *refVarTransformer) replaceVars(in interface{}) (interface{}, error) {
for k, v := range inMap {
s, ok := v.(string)
if !ok {
// This field not contain a $(VAR) since it is not
// This field can not contain a $(VAR) since it is not
// of string type. For instance .spec.replicas: 3 in
// a Deployment object
xs[k] = v
@@ -64,7 +68,7 @@ func (rv *refVarTransformer) replaceVars(in interface{}) (interface{}, error) {
case interface{}:
s, ok := in.(string)
if !ok {
// This field not contain a $(VAR) since it is not of string type.
// This field can not contain a $(VAR) since it is not of string type.
return in, nil
}
// This field can potentially contain a $(VAR) since it is

View File

@@ -29,6 +29,7 @@ func TestRefVarTransformer(t *testing.T) {
description string
given given
expected expected
errMessage string
}{
{
description: "var replacement in map[string]",
@@ -111,6 +112,27 @@ func TestRefVarTransformer(t *testing.T) {
unused: []string{"BAR"},
},
},
{
description: "var replacement panic in map[string]",
given: given{
varMap: map[string]interface{}{},
fs: []types.FieldSpec{
{Gvk: resid.Gvk{Version: "v1", Kind: "ConfigMap"}, Path: "data/slice"},
},
res: resmaptest_test.NewRmBuilder(
t, resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
},
"data": map[string]interface{}{
"slice": []interface{}{5}, // noticeably *not* a []string
}}).ResMap(),
},
errMessage: "expected array of strings, found [5]",
},
}
for _, tc := range testCases {
@@ -122,16 +144,23 @@ func TestRefVarTransformer(t *testing.T) {
err := tr.Transform(tc.given.res)
// assert
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if tc.errMessage != "" {
if err == nil {
t.Fatalf("missing expected error %v", tc.errMessage)
} else if err.Error() != tc.errMessage {
t.Fatalf("actual error doesn't match expected error: \nACTUAL: %v\nEXPECTED: %v", err.Error(), tc.errMessage)
}
} else {
if err != nil {
t.Errorf("unexpected error: %v", err)
}
a, e := tc.given.res, tc.expected.res
if !reflect.DeepEqual(a, e) {
err = e.ErrorIfNotEqualLists(a)
t.Fatalf("actual doesn't match expected: \nACTUAL:\n%v\nEXPECTED:\n%v\nERR: %v", a, e, err)
a, e := tc.given.res, tc.expected.res
if !reflect.DeepEqual(a, e) {
err = e.ErrorIfNotEqualLists(a)
t.Fatalf("actual doesn't match expected: \nACTUAL:\n%v\nEXPECTED:\n%v\nERR: %v", a, e, err)
}
}
})
}
}

View File

@@ -1,6 +1,6 @@
module sigs.k8s.io/kustomize/api/internal/crawl
go 1.12
go 1.13
require (
github.com/elastic/go-elasticsearch/v6 v6.8.5
@@ -8,6 +8,8 @@ require (
github.com/gorilla/mux v1.7.3
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79
github.com/rs/cors v1.7.0
sigs.k8s.io/kustomize/api v0.3.1
sigs.k8s.io/yaml v1.1.0
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)
replace sigs.k8s.io/kustomize/api v0.0.0 => ../../../api

View File

@@ -1,6 +1,7 @@
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/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
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=
@@ -12,6 +13,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
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=
@@ -19,11 +21,17 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
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/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -32,6 +40,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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=
@@ -40,6 +49,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
github.com/elastic/go-elasticsearch/v6 v6.8.5 h1:U2HtkBseC1FNBmDr0TR2tKltL6FxoY+niDAlj5M8TK8=
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
@@ -53,6 +63,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
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/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA=
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-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@@ -65,7 +76,7 @@ github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
@@ -143,6 +154,12 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:Fecb
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/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.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
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=
@@ -168,7 +185,6 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
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/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
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=
@@ -183,8 +199,12 @@ github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
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=
@@ -193,6 +213,7 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
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/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -206,6 +227,7 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
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/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
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=
@@ -223,17 +245,21 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
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.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -243,6 +269,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
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.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
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.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -255,6 +282,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
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.2.3-0.20181224173747-660f15d67dbb/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=
@@ -262,6 +290,8 @@ github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiff
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
@@ -270,9 +300,14 @@ github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk
github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
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=
github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM=
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@@ -281,7 +316,6 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -291,6 +325,7 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/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=
@@ -308,6 +343,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/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/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/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/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -328,10 +365,11 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c h1:Vco5b+cuG5NNfORVxZy6bYZQ7rsigisU1WQFkvQ0L5E=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/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.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -353,7 +391,6 @@ golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/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-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -387,6 +424,10 @@ 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.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
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.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
@@ -407,9 +448,10 @@ k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/api v0.3.1 h1:oqMIXvS6tFEUVuKIRUKDa05eC4Hh+cb9JYg8Zhp2d24=
sigs.k8s.io/kustomize/api v0.3.1/go.mod h1:A+ATnlHqzictQfQC1q3KB/T6MSr0UWQsrrLxMWkge2E=
sigs.k8s.io/kustomize/kyaml v0.1.10/go.mod h1:mPmeBSRy0LTMv6fSrYSoi2yIFNZVouGKDsTekE5kdhs=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

View File

@@ -25,8 +25,7 @@ func makeFreshConfigMap(
}
// MakeConfigMap returns a new ConfigMap, or nil and an error.
func (f *Factory) MakeConfigMap(
args *types.ConfigMapArgs) (*corev1.ConfigMap, error) {
func (f *Factory) MakeConfigMap(args *types.ConfigMapArgs) (*corev1.ConfigMap, error) {
all, err := f.kvLdr.Load(args.KvPairSources)
if err != nil {
return nil, errors.Wrap(err, "loading KV pairs")
@@ -38,7 +37,7 @@ func (f *Factory) MakeConfigMap(
return nil, errors.Wrap(err, "trouble mapping")
}
}
f.setLabelsAndAnnnotations(cm, args.GeneratorOptions)
f.copyLabelsAndAnnotations(cm, args.Options)
return cm, nil
}

View File

@@ -82,7 +82,6 @@ func TestConstructConfigMap(t *testing.T) {
type testCase struct {
description string
input types.ConfigMapArgs
options *types.GeneratorOptions
expected *corev1.ConfigMap
}
@@ -99,7 +98,6 @@ func TestConstructConfigMap(t *testing.T) {
},
},
},
options: nil,
expected: makeEnvConfigMap("envConfigMap"),
},
{
@@ -115,7 +113,6 @@ func TestConstructConfigMap(t *testing.T) {
},
},
},
options: nil,
expected: makeFileConfigMap("fileConfigMap"),
},
{
@@ -126,11 +123,11 @@ func TestConstructConfigMap(t *testing.T) {
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
},
},
options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
},
},
expected: makeLiteralConfigMap("literalConfigMap", map[string]string{
@@ -145,7 +142,7 @@ func TestConstructConfigMap(t *testing.T) {
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
GeneratorOptions: &types.GeneratorOptions{
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "changed",
"cat": "dog",
@@ -157,18 +154,6 @@ func TestConstructConfigMap(t *testing.T) {
},
},
},
options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
Annotations: map[string]string{
"foo": "bar",
},
},
// GeneratorOptions from the ConfigMapArgs take precedence over the
// factory level GeneratorOptions and should overwrite
// labels/annotations set in the factory level if there are common
// labels/annotations
expected: makeLiteralConfigMap("literalConfigMap", map[string]string{
"foo": "changed",
"cat": "dog",
@@ -193,8 +178,7 @@ func TestConstructConfigMap(t *testing.T) {
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator())
for _, tc := range testCases {
f := NewFactory(kvLdr, tc.options)
cm, err := f.MakeConfigMap(&tc.input)
cm, err := NewFactory(kvLdr).MakeConfigMap(&tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

View File

@@ -11,44 +11,26 @@ import (
// Factory makes ConfigMaps and Secrets.
type Factory struct {
kvLdr ifc.KvLoader
options *types.GeneratorOptions
kvLdr ifc.KvLoader
}
// NewFactory returns a new factory that makes ConfigMaps and Secrets.
func NewFactory(
kvLdr ifc.KvLoader, o *types.GeneratorOptions) *Factory {
return &Factory{kvLdr: kvLdr, options: o}
func NewFactory(kvLdr ifc.KvLoader) *Factory {
return &Factory{kvLdr: kvLdr}
}
// setLabelsAndAnnnotations will take the labels and annotations from
// global GeneratorOptions and resource level GeneratorOptions and merge them
// with the resource level taking precedence, and then set them on the provided
// obj.
func (f *Factory) setLabelsAndAnnnotations(obj metav1.Object, opts *types.GeneratorOptions) {
labels := make(map[string]string)
annotations := make(map[string]string)
if f.options != nil {
for k, v := range f.options.Labels {
labels[k] = v
}
for k, v := range f.options.Annotations {
annotations[k] = v
}
// copyLabelsAndAnnotations copies labels and annotations from
// GeneratorOptions into the given object.
func (f *Factory) copyLabelsAndAnnotations(
obj metav1.Object, opts *types.GeneratorOptions) {
if opts == nil {
return
}
if opts != nil {
for k, v := range opts.Labels {
labels[k] = v
}
for k, v := range opts.Annotations {
annotations[k] = v
}
if opts.Labels != nil {
obj.SetLabels(types.CopyMap(opts.Labels))
}
if len(labels) != 0 {
obj.SetLabels(labels)
}
if len(annotations) != 0 {
obj.SetAnnotations(annotations)
if opts.Annotations != nil {
obj.SetAnnotations(types.CopyMap(opts.Annotations))
}
}

View File

@@ -26,8 +26,7 @@ func makeFreshSecret(
}
// MakeSecret returns a new secret.
func (f *Factory) MakeSecret(
args *types.SecretArgs) (*corev1.Secret, error) {
func (f *Factory) MakeSecret(args *types.SecretArgs) (*corev1.Secret, error) {
all, err := f.kvLdr.Load(args.KvPairSources)
if err != nil {
return nil, err
@@ -39,7 +38,7 @@ func (f *Factory) MakeSecret(
return nil, err
}
}
f.setLabelsAndAnnnotations(s, args.GeneratorOptions)
f.copyLabelsAndAnnotations(s, args.Options)
return s, nil
}

View File

@@ -79,7 +79,6 @@ func TestConstructSecret(t *testing.T) {
type testCase struct {
description string
input types.SecretArgs
options *types.GeneratorOptions
expected *corev1.Secret
}
@@ -94,7 +93,6 @@ func TestConstructSecret(t *testing.T) {
},
},
},
options: nil,
expected: makeEnvSecret("envSecret"),
},
{
@@ -107,7 +105,6 @@ func TestConstructSecret(t *testing.T) {
},
},
},
options: nil,
expected: makeFileSecret("fileSecret"),
},
{
@@ -118,55 +115,22 @@ func TestConstructSecret(t *testing.T) {
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y"},
},
},
},
options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
Options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
Annotations: map[string]string{
"fruit": "banana",
"pet": "dog",
},
},
},
},
expected: makeLiteralSecret("literalSecret", map[string]string{
"foo": "bar",
}, nil),
},
{
description: "construct secret from literal with GeneratorOptions in SecretArgs",
input: types.SecretArgs{
GeneratorArgs: types.GeneratorArgs{
Name: "literalSecret",
KvPairSources: types.KvPairSources{
LiteralSources: []string{"a=x", "b=y"},
},
GeneratorOptions: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "changed",
"cat": "dog",
},
Annotations: map[string]string{
"foo": "changed",
"cat": "dog",
},
},
},
},
options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
Annotations: map[string]string{
"foo": "bar",
},
},
// GeneratorOptions from the SecretArgs take precedence over the
// factory level GeneratorOptions and should overwrite
// labels/annotations set in the factory level if there are common
// labels/annotations
expected: makeLiteralSecret("literalSecret", map[string]string{
"foo": "changed",
"cat": "dog",
}, map[string]string{
"foo": "changed",
"cat": "dog",
"fruit": "banana",
"pet": "dog",
}),
},
}
@@ -178,7 +142,7 @@ func TestConstructSecret(t *testing.T) {
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator())
for _, tc := range testCases {
f := NewFactory(kvLdr, tc.options)
f := NewFactory(kvLdr)
cm, err := f.MakeSecret(&tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)

View File

@@ -13,21 +13,21 @@ func _() {
_ = x[ConfigMapGenerator-2]
_ = x[HashTransformer-3]
_ = x[ImageTagTransformer-4]
_ = x[InventoryTransformer-5]
_ = x[LabelTransformer-6]
_ = x[LegacyOrderTransformer-7]
_ = x[NamespaceTransformer-8]
_ = x[PatchJson6902Transformer-9]
_ = x[PatchStrategicMergeTransformer-10]
_ = x[PatchTransformer-11]
_ = x[PrefixSuffixTransformer-12]
_ = x[ReplicaCountTransformer-13]
_ = x[SecretGenerator-14]
_ = x[LabelTransformer-5]
_ = x[LegacyOrderTransformer-6]
_ = x[NamespaceTransformer-7]
_ = x[PatchJson6902Transformer-8]
_ = x[PatchStrategicMergeTransformer-9]
_ = x[PatchTransformer-10]
_ = x[PrefixSuffixTransformer-11]
_ = x[ReplicaCountTransformer-12]
_ = x[SecretGenerator-13]
_ = x[ValueAddTransformer-14]
}
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerInventoryTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGenerator"
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformer"
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 101, 117, 139, 159, 183, 213, 229, 252, 275, 290}
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 97, 119, 139, 163, 193, 209, 232, 255, 270, 289}
func (i BuiltinPluginType) String() string {
if i < 0 || i >= BuiltinPluginType(len(_BuiltinPluginType_index)-1) {

View File

@@ -17,7 +17,6 @@ const (
ConfigMapGenerator
HashTransformer
ImageTagTransformer
InventoryTransformer
LabelTransformer
LegacyOrderTransformer
NamespaceTransformer
@@ -27,6 +26,7 @@ const (
PrefixSuffixTransformer
ReplicaCountTransformer
SecretGenerator
ValueAddTransformer
)
var stringToBuiltinPluginTypeMap map[string]BuiltinPluginType
@@ -63,7 +63,6 @@ var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin
AnnotationsTransformer: builtins.NewAnnotationsTransformerPlugin,
HashTransformer: builtins.NewHashTransformerPlugin,
ImageTagTransformer: builtins.NewImageTagTransformerPlugin,
InventoryTransformer: builtins.NewInventoryTransformerPlugin,
LabelTransformer: builtins.NewLabelTransformerPlugin,
LegacyOrderTransformer: builtins.NewLegacyOrderTransformerPlugin,
NamespaceTransformer: builtins.NewNamespaceTransformerPlugin,
@@ -72,4 +71,5 @@ var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin
PatchTransformer: builtins.NewPatchTransformerPlugin,
PrefixSuffixTransformer: builtins.NewPrefixSuffixTransformerPlugin,
ReplicaCountTransformer: builtins.NewReplicaCountTransformerPlugin,
ValueAddTransformer: builtins.NewValueAddTransformerPlugin,
}

View File

@@ -6,143 +6,85 @@ package compiler
import (
"bytes"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"time"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/konfig"
)
// Compiler creates Go plugin object files.
//
// Source code is read from
// ${srcRoot}/${g}/${v}/${k}.go
//
// Object code is written to
// ${objRoot}/${g}/${v}/${k}.so
type Compiler struct {
srcRoot string
objRoot string
}
// DeterminePluginSrcRoot guesses where the user
// has her ${g}/${v}/$lower(${k})/${k}.go files.
func DeterminePluginSrcRoot(fSys filesys.FileSystem) (string, error) {
return konfig.FirstDirThatExistsElseError(
"source directory", fSys, []konfig.NotedFunc{
{
Note: "relative to unit test",
F: func() string {
return filepath.Clean(
filepath.Join(
os.Getenv("PWD"),
"..", "..",
konfig.RelPluginHome))
},
},
{
Note: "relative to unit test (internal pkg)",
F: func() string {
return filepath.Clean(
filepath.Join(
os.Getenv("PWD"),
"..", "..", "..", "..",
konfig.RelPluginHome))
},
},
{
Note: "relative to api package",
F: func() string {
return filepath.Clean(
filepath.Join(
os.Getenv("PWD"),
"..", "..", "..",
konfig.RelPluginHome))
},
},
{
Note: "old style $GOPATH",
F: func() string {
return filepath.Join(
os.Getenv("GOPATH"),
"src", konfig.DomainName,
konfig.ProgramName, konfig.RelPluginHome)
},
},
{
Note: "HOME with literal 'gopath'",
F: func() string {
return filepath.Join(
konfig.HomeDir(), "gopath",
"src", konfig.DomainName,
konfig.ProgramName, konfig.RelPluginHome)
},
},
{
Note: "home directory",
F: func() string {
return filepath.Join(
konfig.HomeDir(), konfig.DomainName,
konfig.ProgramName, konfig.RelPluginHome)
},
},
})
// pluginRoot is where the user
// has her ${g}/${v}/$lower(${k})/${k}.go files.
pluginRoot string
// Where compilation happens.
workDir string
// Used as the root file name for src and object.
rawKind string
// Capture compiler output.
stderr bytes.Buffer
// Capture compiler output.
stdout bytes.Buffer
}
// NewCompiler returns a new compiler instance.
func NewCompiler(srcRoot, objRoot string) *Compiler {
return &Compiler{srcRoot: srcRoot, objRoot: objRoot}
func NewCompiler(root string) *Compiler {
return &Compiler{pluginRoot: root}
}
// ObjRoot is root of compilation target tree.
func (b *Compiler) ObjRoot() string {
return b.objRoot
// Set GVK converts g,v,k tuples to file path components.
func (b *Compiler) SetGVK(g, v, k string) {
b.rawKind = k
b.workDir = filepath.Join(b.pluginRoot, g, v, strings.ToLower(k))
}
// SrcRoot is where to find src.
func (b *Compiler) SrcRoot() string {
return b.srcRoot
func (b *Compiler) srcPath() string {
return filepath.Join(b.workDir, b.rawKind+".go")
}
func goBin() string {
return filepath.Join(runtime.GOROOT(), "bin", "go")
func (b *Compiler) objFile() string {
return b.rawKind + ".so"
}
// Compile reads ${srcRoot}/${g}/${v}/${k}.go
// and writes ${objRoot}/${g}/${v}/${k}.so
func (b *Compiler) Compile(g, v, k string) error {
lowK := strings.ToLower(k)
objDir := filepath.Join(b.objRoot, g, v, lowK)
objFile := filepath.Join(objDir, k) + ".so"
if RecentFileExists(objFile) {
// Skip rebuilding it.
// Absolute path to the compiler output (the .so file).
func (b *Compiler) ObjPath() string {
return filepath.Join(b.workDir, b.objFile())
}
// Cleanup provides a hook to delete the .so file.
// Ignore errors.
func (b *Compiler) Cleanup() {
_ = os.Remove(b.ObjPath())
}
// Compile changes its working directory to
// ${pluginRoot}/${g}/${v}/$lower(${k} and places
// object code next to source code.
func (b *Compiler) Compile() error {
if FileYoungerThan(b.ObjPath(), 8*time.Second) {
// Skip rebuilding it, to save time in a plugin test file
// that has many distinct calls to make a harness and compile
// the plugin (only the first compile will happen).
// Make it a short time to avoid tricking someone who's actively
// developing a plugin.
return nil
}
err := os.MkdirAll(objDir, os.ModePerm)
if err != nil {
return err
}
srcFile := filepath.Join(b.srcRoot, g, v, lowK, k) + ".go"
if !FileExists(srcFile) {
// Handy for tests of lone plugins.
s := k + ".go"
if !FileExists(s) {
return fmt.Errorf(
"cannot find source at '%s' or '%s'", srcFile, s)
}
srcFile = s
if !FileExists(b.srcPath()) {
return fmt.Errorf("cannot find source at '%s'", b.srcPath())
}
// If you use an IDE, make sure it's go build and test flags
// match those used below. Same goes for Makefile targets.
commands := []string{
"build",
// "-trimpath", This flag used to make it better, now it makes it worse,
// see https://github.com/golang/go/issues/31354
"-buildmode",
"plugin",
"-o", objFile, srcFile,
"-o", b.objFile(),
}
goBin := goBin()
if !FileExists(goBin) {
@@ -150,34 +92,26 @@ func (b *Compiler) Compile(g, v, k string) error {
"cannot find go compiler %s", goBin)
}
cmd := exec.Command(goBin, commands...)
var stderr bytes.Buffer
cmd.Stderr = &stderr
b.stderr.Reset()
cmd.Stderr = &b.stderr
b.stdout.Reset()
cmd.Stdout = &b.stdout
cmd.Env = os.Environ()
cmd.Dir = b.workDir
if err := cmd.Run(); err != nil {
b.report()
return errors.Wrapf(
err, "cannot compile %s:\nSTDERR\n%s\n", srcFile, stderr.String())
err, "cannot compile %s:\nSTDERR\n%s\n",
b.srcPath(), b.stderr.String())
}
return nil
}
// True if file less than 3 minutes old, i.e. not
// accidentally left over from some earlier build.
func RecentFileExists(path string) bool {
fi, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return false
}
}
age := time.Since(fi.ModTime())
return age.Minutes() < 3
}
func FileExists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
func (b *Compiler) report() {
log.Println("stdout: -------")
log.Println(b.stdout.String())
log.Println("----------------")
log.Println("stderr: -------")
log.Println(b.stderr.String())
log.Println("----------------")
}

View File

@@ -4,8 +4,6 @@
package compiler_test
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
@@ -15,53 +13,46 @@ import (
// Regression coverage over compiler behavior.
func TestCompiler(t *testing.T) {
configRoot, err := ioutil.TempDir("", "kustomize-compiler-test")
if err != nil {
t.Errorf("failed to make temp dir: %v", err)
}
srcRoot, err := DeterminePluginSrcRoot(filesys.MakeFsOnDisk())
if err != nil {
t.Error(err)
}
c := NewCompiler(srcRoot, configRoot)
if configRoot != c.ObjRoot() {
t.Errorf("unexpected objRoot %s", c.ObjRoot())
}
c := NewCompiler(srcRoot)
c.SetGVK("someteam.example.com", "v1", "DatePrefixer")
expectObj := filepath.Join(
c.ObjRoot(),
"someteam.example.com", "v1", "dateprefixer", "DatePrefixer.so")
if FileExists(expectObj) {
t.Errorf("obj file should not exist yet: %s", expectObj)
srcRoot, "someteam.example.com", "v1", "dateprefixer", "DatePrefixer.so")
if expectObj != c.ObjPath() {
t.Errorf("Expected '%s', got '%s'", expectObj, c.ObjPath())
}
err = c.Compile("someteam.example.com", "v1", "DatePrefixer")
err = c.Compile()
if err != nil {
t.Error(err)
}
if !RecentFileExists(expectObj) {
if !FileExists(expectObj) {
t.Errorf("didn't find expected obj file %s", expectObj)
}
c.Cleanup()
if FileExists(expectObj) {
t.Errorf("obj file '%s' should be gone", expectObj)
}
c.SetGVK("builtin", "", "SecretGenerator")
expectObj = filepath.Join(
c.ObjRoot(),
srcRoot,
"builtin", "", "secretgenerator", "SecretGenerator.so")
if FileExists(expectObj) {
t.Errorf("obj file should not exist yet: %s", expectObj)
if expectObj != c.ObjPath() {
t.Errorf("Expected '%s', got '%s'", expectObj, c.ObjPath())
}
err = c.Compile("builtin", "", "SecretGenerator")
err = c.Compile()
if err != nil {
t.Error(err)
}
if !RecentFileExists(expectObj) {
if !FileExists(expectObj) {
t.Errorf("didn't find expected obj file %s", expectObj)
}
err = os.RemoveAll(c.ObjRoot())
if err != nil {
t.Errorf(
"removing temp dir: %s %v", c.ObjRoot(), err)
}
c.Cleanup()
if FileExists(expectObj) {
t.Errorf("cleanup failed; still see: %s", expectObj)
t.Errorf("obj file '%s' should be gone", expectObj)
}
}

View File

@@ -0,0 +1,115 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package compiler
import (
"os"
"path/filepath"
"runtime"
"time"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/konfig"
)
func goBin() string {
return filepath.Join(runtime.GOROOT(), "bin", "go")
}
// DeterminePluginSrcRoot guesses where the user
// has her ${g}/${v}/$lower(${k})/${k}.go files.
func DeterminePluginSrcRoot(fSys filesys.FileSystem) (string, error) {
return konfig.FirstDirThatExistsElseError(
"source directory", fSys, []konfig.NotedFunc{
{
Note: "relative to unit test",
F: func() string {
return filepath.Clean(
filepath.Join(
os.Getenv("PWD"),
"..", "..",
konfig.RelPluginHome))
},
},
{
Note: "relative to unit test (internal pkg)",
F: func() string {
return filepath.Clean(
filepath.Join(
os.Getenv("PWD"),
"..", "..", "..", "..",
konfig.RelPluginHome))
},
},
{
Note: "relative to api package",
F: func() string {
return filepath.Clean(
filepath.Join(
os.Getenv("PWD"),
"..", "..", "..",
konfig.RelPluginHome))
},
},
{
Note: "old style $GOPATH",
F: func() string {
return filepath.Join(
os.Getenv("GOPATH"),
"src", konfig.DomainName,
konfig.ProgramName, konfig.RelPluginHome)
},
},
{
Note: "HOME with literal 'gopath'",
F: func() string {
return filepath.Join(
konfig.HomeDir(), "gopath",
"src", konfig.DomainName,
konfig.ProgramName, konfig.RelPluginHome)
},
},
{
Note: "home directory",
F: func() string {
return filepath.Join(
konfig.HomeDir(), konfig.DomainName,
konfig.ProgramName, konfig.RelPluginHome)
},
},
})
}
// FileYoungerThan returns true if the file both exists and has an
// age is <= the Duration argument.
func FileYoungerThan(path string, d time.Duration) bool {
fi, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return false
}
}
return time.Since(fi.ModTime()) <= d
}
// FileModifiedAfter returns true if the file both exists and was
// modified after the given time..
func FileModifiedAfter(path string, t time.Time) bool {
fi, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return false
}
}
return fi.ModTime().After(t)
}
func FileExists(path string) bool {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}

View File

@@ -0,0 +1,26 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package compiler
import (
"path/filepath"
"strings"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
)
func TestDeterminePluginSrcRoot(t *testing.T) {
actual, err := DeterminePluginSrcRoot(filesys.MakeFsOnDisk())
if err != nil {
t.Error(err)
}
if !filepath.IsAbs(actual) {
t.Errorf("expected absolute path, but got '%s'", actual)
}
expectedSuffix := filepath.Join("sigs.k8s.io", "kustomize", "plugin")
if !strings.HasSuffix(actual, expectedSuffix) {
t.Errorf("expected suffix '%s' in '%s'", expectedSuffix, actual)
}
}

View File

@@ -94,7 +94,7 @@ TO GENERATE CODE
cd $repo/plugin/builtin
go generate ./...
See travis/pre-commit.sh for canonical way
See travis/kyaml-pre-commit.sh for canonical way
to execute the above.
This creates

View File

@@ -266,8 +266,9 @@ func (p *ExecPlugin) UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, err
}
r.SetAnnotations(annotations)
r.SetOptions(types.NewGenArgs(
&types.GeneratorArgs{Behavior: behavior},
&types.GeneratorOptions{DisableNameSuffixHash: !needsHash}))
&types.GeneratorArgs{
Behavior: behavior,
Options: &types.GeneratorOptions{DisableNameSuffixHash: !needsHash}}))
}
return rm, nil
}

View File

@@ -116,7 +116,9 @@ func makeConfigMapOptions(rf *resource.Factory, name, behavior string, disableHa
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{"name": name},
}, &types.GeneratorArgs{Behavior: behavior}, &types.GeneratorOptions{DisableNameSuffixHash: disableHash})
}, &types.GeneratorArgs{
Behavior: behavior,
Options: &types.GeneratorOptions{DisableNameSuffixHash: disableHash}})
}
func strptr(s string) *string {

View File

@@ -22,6 +22,7 @@ import (
"sigs.k8s.io/kustomize/api/types"
)
// Loader loads plugins using a file loader (a different loader).
type Loader struct {
pc *types.PluginConfig
rf *resmap.Factory
@@ -107,17 +108,35 @@ func isBuiltinPlugin(res *resource.Resource) bool {
}
func (l *Loader) loadAndConfigurePlugin(
ldr ifc.Loader, v ifc.Validator, res *resource.Resource) (c resmap.Configurable, err error) {
ldr ifc.Loader,
v ifc.Validator,
res *resource.Resource) (c resmap.Configurable, err error) {
if isBuiltinPlugin(res) {
// Instead of looking for and loading a .so file, just
// instantiate the plugin from a generated factory
// function (see "pluginator"). Being able to do this
// is what makes a plugin "builtin".
c, err = l.makeBuiltinPlugin(res.GetGvk())
} else if l.pc.PluginRestrictions == types.PluginRestrictionsNone {
c, err = l.loadPlugin(res.OrgId())
switch l.pc.BpLoadingOptions {
case types.BploLoadFromFileSys:
c, err = l.loadPlugin(res.OrgId())
case types.BploUseStaticallyLinked:
// Instead of looking for and loading a .so file,
// instantiate the plugin from a generated factory
// function (see "pluginator"). Being able to do this
// is what makes a plugin "builtin".
c, err = l.makeBuiltinPlugin(res.GetGvk())
default:
err = fmt.Errorf(
"unknown plugin loader behavior specified: %v",
l.pc.BpLoadingOptions)
}
} else {
err = types.NewErrOnlyBuiltinPluginsAllowed(res.OrgId().Kind)
switch l.pc.PluginRestrictions {
case types.PluginRestrictionsNone:
c, err = l.loadPlugin(res.OrgId())
case types.PluginRestrictionsBuiltinsOnly:
err = types.NewErrOnlyBuiltinPluginsAllowed(res.OrgId().Kind)
default:
err = fmt.Errorf(
"unknown plugin restriction specified: %v",
l.pc.PluginRestrictions)
}
}
if err != nil {
return nil, err

View File

@@ -15,6 +15,7 @@ import (
"sigs.k8s.io/kustomize/api/resource"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
)
const (
@@ -58,22 +59,26 @@ func TestLoader(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c, err := konfig.EnabledPluginConfig()
if err != nil {
t.Fatal(err)
}
pLdr := NewLoader(c, rmF)
if pLdr == nil {
t.Fatal("expect non-nil loader")
}
m, err := rmF.NewResMapFromBytes([]byte(
generatorConfigs, err := rmF.NewResMapFromBytes([]byte(
someServiceGenerator + "---\n" + secretGenerator))
if err != nil {
t.Fatal(err)
}
_, err = pLdr.LoadGenerators(
fLdr, valtest_test.MakeFakeValidator(), m)
if err != nil {
t.Fatal(err)
for _, behavior := range []types.BuiltinPluginLoadingOptions{
types.BploUseStaticallyLinked,
types.BploLoadFromFileSys} {
c, err := konfig.EnabledPluginConfig(behavior)
if err != nil {
t.Fatal(err)
}
pLdr := NewLoader(c, rmF)
if pLdr == nil {
t.Fatal("expect non-nil loader")
}
_, err = pLdr.LoadGenerators(
fLdr, valtest_test.MakeFakeValidator(), generatorConfigs)
if err != nil {
t.Fatal(err)
}
}
}

View File

@@ -106,15 +106,10 @@ func unmarshal(y []byte, o interface{}) error {
// MakeCustomizedResMap creates a fully customized ResMap
// per the instructions contained in its kustomiztion instance.
func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) {
return kt.makeCustomizedResMap(types.GarbageIgnore)
return kt.makeCustomizedResMap()
}
func (kt *KustTarget) MakePruneConfigMap() (resmap.ResMap, error) {
return kt.makeCustomizedResMap(types.GarbageCollect)
}
func (kt *KustTarget) makeCustomizedResMap(
garbagePolicy types.GarbagePolicy) (resmap.ResMap, error) {
func (kt *KustTarget) makeCustomizedResMap() (resmap.ResMap, error) {
ra, err := kt.AccumulateTarget()
if err != nil {
return nil, err
@@ -141,11 +136,6 @@ func (kt *KustTarget) makeCustomizedResMap(
return nil, err
}
err = kt.computeInventory(ra, garbagePolicy)
if err != nil {
return nil, err
}
return ra.ResMap(), nil
}
@@ -159,35 +149,6 @@ func (kt *KustTarget) addHashesToNames(
return ra.Transform(p)
}
func (kt *KustTarget) computeInventory(
ra *accumulator.ResAccumulator, garbagePolicy types.GarbagePolicy) error {
inv := kt.kustomization.Inventory
if inv == nil {
return nil
}
if inv.Type != "ConfigMap" {
return fmt.Errorf("don't know how to do that")
}
if inv.ConfigMap.Namespace != kt.kustomization.Namespace {
return fmt.Errorf("namespace mismatch")
}
var c struct {
Policy string
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
}
c.Name = inv.ConfigMap.Name
c.Namespace = inv.ConfigMap.Namespace
c.Policy = garbagePolicy.String()
p := builtins.NewInventoryTransformerPlugin()
err := kt.configureBuiltinPlugin(p, c, builtinhelpers.InventoryTransformer)
if err != nil {
return err
}
return ra.Transform(p)
}
// AccumulateTarget returns a new ResAccumulator,
// holding customized resources and the data/rules used
// to do so. The name back references and vars are
@@ -364,7 +325,8 @@ func (kt *KustTarget) configureBuiltinPlugin(
}
err = p.Config(resmap.NewPluginHelpers(kt.ldr, kt.validator, kt.rFactory), y)
if err != nil {
return errors.Wrapf(err, "builtin %s config: %v", bpt, y)
return errors.Wrapf(
err, "trouble configuring builtin %s with config: `\n%s`", bpt, string(y))
}
return nil
}

View File

@@ -4,6 +4,8 @@
package target
import (
"fmt"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
"sigs.k8s.io/kustomize/api/resmap"
@@ -74,14 +76,12 @@ var generatorConfigurators = map[builtinhelpers.BuiltinPluginType]func(
builtinhelpers.SecretGenerator: func(kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f gFactory) (
result []resmap.Generator, err error) {
var c struct {
types.GeneratorOptions
types.SecretArgs
}
if kt.kustomization.GeneratorOptions != nil {
c.GeneratorOptions = *kt.kustomization.GeneratorOptions
}
for _, args := range kt.kustomization.SecretGenerator {
c.SecretArgs = args
c.SecretArgs.Options = types.MergeGlobalOptionsIntoLocal(
c.SecretArgs.Options, kt.kustomization.GeneratorOptions)
p := f()
err := kt.configureBuiltinPlugin(p, c, bpt)
if err != nil {
@@ -95,14 +95,12 @@ var generatorConfigurators = map[builtinhelpers.BuiltinPluginType]func(
builtinhelpers.ConfigMapGenerator: func(kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f gFactory) (
result []resmap.Generator, err error) {
var c struct {
types.GeneratorOptions
types.ConfigMapArgs
}
if kt.kustomization.GeneratorOptions != nil {
c.GeneratorOptions = *kt.kustomization.GeneratorOptions
}
for _, args := range kt.kustomization.ConfigMapGenerator {
c.ConfigMapArgs = args
c.ConfigMapArgs.Options = types.MergeGlobalOptionsIntoLocal(
c.ConfigMapArgs.Options, kt.kustomization.GeneratorOptions)
p := f()
err := kt.configureBuiltinPlugin(p, c, bpt)
if err != nil {
@@ -294,4 +292,10 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
}
return
},
// No kustomization file keyword for this yet.
builtinhelpers.ValueAddTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
return nil, fmt.Errorf("valueadd keyword not yet defined")
},
}

View File

@@ -7,7 +7,6 @@ import (
"encoding/base64"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/resmap"
@@ -19,8 +18,7 @@ import (
// high level tests.
func TestMakeCustomizedResMap(t *testing.T) {
fSys := filesys.MakeFsInMemory()
th := kusttest_test.MakeHarnessWithFs(t, fSys)
th := kusttest_test.MakeHarness(t)
th.WriteK("/whatever", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
@@ -168,7 +166,7 @@ metadata:
}
actual, err := makeKustTargetWithRf(
t, fSys, "/whatever", resFactory).MakeCustomizedResMap()
t, th.GetFSys(), "/whatever", resFactory).MakeCustomizedResMap()
if err != nil {
t.Fatalf("unexpected Resources error %v", err)
}

View File

@@ -1,12 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package inventory
const (
// Annotation that contains the inventory content.
ContentAnnotation = "kustomize.config.k8s.io/Inventory"
// Annotation for inventory content hash.
HashAnnotation = "kustomize.config.k8s.io/InventoryHash"
)

View File

@@ -1,235 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package inventory
import (
"encoding/json"
"sigs.k8s.io/kustomize/api/resid"
)
//Refs is a reference map. Each key is the id
//of a k8s resource, and each value is a list of
//object ids that refer back to the object in the
//key.
//For example, the key could correspond to a
//ConfigMap, and the list of values might include
//several different Deployments that get data from
//that ConfigMap (and thus refer to it).
//References are important in inventory management
//because one may not delete an object before all
//objects referencing it have been removed.
type Refs map[resid.ResId][]resid.ResId
func NewRefs() Refs {
return Refs{}
}
// Merge merges a Refs into an existing Refs
func (rf Refs) Merge(b Refs) Refs {
for key, value := range b {
_, ok := rf[key]
if ok {
rf[key] = append(rf[key], value...)
} else {
rf[key] = value
}
}
return rf
}
// removeIfContains removes the reference relationship
// a --> b
// from the Refs if it exists
func (rf Refs) RemoveIfContains(a, b resid.ResId) {
refs, ok := rf[a]
if !ok {
return
}
for i, ref := range refs {
if ref.Equals(b) {
rf[a] = append(refs[:i], refs[i+1:]...)
break
}
}
}
//Inventory is a an object intended for
//serialization into the annotations of a so-called
//apply-root object (a ConfigMap, an Application,
//etc.) living in the cluster. This apply-root
//object is written as part of an apply operation as
//a means to record overall cluster state changes.
//At the end of a successful apply, the "current"
//field in Inventory will be a map whose keys all
//correspond to an object in the cluster, and
//"previous" will be the previous such set (an empty
//set on the first apply).
//An Inventory allows the Prune method to work.
type Inventory struct {
Current Refs `json:"current,omitempty"`
Previous Refs `json:"previous,omitempty"`
}
// NewInventory returns an Inventory object
func NewInventory() *Inventory {
return &Inventory{
Current: NewRefs(),
Previous: NewRefs(),
}
}
// UpdateCurrent updates the Inventory given a
// new current Refs
// The existing Current refs is merged into
// the Previous refs
func (a *Inventory) UpdateCurrent(curref Refs) *Inventory {
if len(a.Previous) > 0 {
a.Previous.Merge(a.Current)
} else {
a.Previous = a.Current
}
a.Current = curref
return a
}
func (a *Inventory) removeNewlyOrphanedItemsFromPrevious() []resid.ResId {
var results []resid.ResId
for item, refs := range a.Previous {
if _, ok := a.Current[item]; ok {
delete(a.Previous, item)
continue
}
var newRefs []resid.ResId
toDelete := true
for _, ref := range refs {
if _, ok := a.Current[ref]; ok {
toDelete = false
newRefs = append(newRefs, ref)
}
}
if toDelete {
results = append(results, item)
delete(a.Previous, item)
} else {
a.Previous[item] = newRefs
}
}
return results
}
func (a *Inventory) removeOrphanedItemsFromPreviousThatAreNotInCurrent() []resid.ResId {
var results []resid.ResId
for item, refs := range a.Previous {
if _, ok := a.Current[item]; ok {
continue
}
if len(refs) == 0 {
results = append(results, item)
delete(a.Previous, item)
}
}
return results
}
func (a *Inventory) removeOrphanedItemsFromPreviousThatAreInCurrent() {
//Remove references from Previous that are already in Current refs
for item, refs := range a.Current {
for _, ref := range refs {
a.Previous.RemoveIfContains(item, ref)
}
}
//Remove items from Previous that are already in Current refs
for item, refs := range a.Previous {
if len(refs) == 0 {
if _, ok := a.Current[item]; ok {
delete(a.Previous, item)
}
}
}
}
// Prune computes the diff of Current refs and Previous refs
// and returns a list of Items that can be pruned.
// An item that can be pruned shows up only in Previous refs.
// Prune also updates the Previous refs with those items removed
func (a *Inventory) Prune() []resid.ResId {
a.removeOrphanedItemsFromPreviousThatAreInCurrent()
// These are candidates for deletion from the cluster.
removable1 := a.removeOrphanedItemsFromPreviousThatAreNotInCurrent()
removable2 := a.removeNewlyOrphanedItemsFromPrevious()
return append(removable1, removable2...)
}
// inventory is the internal type used for serialization
type inventory struct {
Current map[string][]resid.ResId `json:"current,omitempty"`
Previous map[string][]resid.ResId `json:"previous,omitempty"`
}
func (a *Inventory) toInternalType() inventory {
prev := map[string][]resid.ResId{}
curr := map[string][]resid.ResId{}
for id, refs := range a.Current {
curr[id.String()] = refs
}
for id, refs := range a.Previous {
prev[id.String()] = refs
}
return inventory{
Current: curr,
Previous: prev,
}
}
func (a *Inventory) fromInternalType(i *inventory) {
for s, refs := range i.Previous {
a.Previous[resid.FromString(s)] = refs
}
for s, refs := range i.Current {
a.Current[resid.FromString(s)] = refs
}
}
func (a *Inventory) marshal() ([]byte, error) {
return json.Marshal(a.toInternalType())
}
func (a *Inventory) unMarshal(data []byte) error {
inv := &inventory{
Current: map[string][]resid.ResId{},
Previous: map[string][]resid.ResId{},
}
err := json.Unmarshal(data, inv)
if err != nil {
return err
}
a.fromInternalType(inv)
return nil
}
// UpdateAnnotations update the annotation map
func (a *Inventory) UpdateAnnotations(annot map[string]string) error {
data, err := a.marshal()
if err != nil {
return err
}
annot[ContentAnnotation] = string(data)
return nil
}
// LoadFromAnnotation loads the Inventory date from the annotation map
func (a *Inventory) LoadFromAnnotation(annot map[string]string) error {
value, ok := annot[ContentAnnotation]
if ok {
return a.unMarshal([]byte(value))
}
return nil
}

View File

@@ -1,60 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package inventory_test
import (
"testing"
. "sigs.k8s.io/kustomize/api/inventory"
"sigs.k8s.io/kustomize/api/resid"
)
func makeRefs() (Refs, Refs) {
a := resid.FromString("G1_V1_K1|ns1|nm1")
b := resid.FromString("G2_V2_K2|ns2|nm2")
c := resid.FromString("G3_V3_K3|ns3|nm3")
current := NewRefs()
current[a] = []resid.ResId{b, c}
current[b] = []resid.ResId{}
current[c] = []resid.ResId{}
newRefs := NewRefs()
newRefs[a] = []resid.ResId{b}
newRefs[b] = []resid.ResId{}
return current, newRefs
}
func TestInventory(t *testing.T) {
inventory := NewInventory()
curref, _ := makeRefs()
inventory.UpdateCurrent(curref)
if len(inventory.Current) != 3 {
t.Fatalf("not getting the correct inventory %v", inventory)
}
curref, newref := makeRefs()
inventory.UpdateCurrent(curref)
if len(inventory.Current) != 3 {
t.Fatalf("not getting the corrent inventory %v", inventory)
}
if len(inventory.Previous) != 3 {
t.Fatalf("not getting the corrent inventory %v", inventory)
}
items := inventory.Prune()
if len(items) != 0 {
t.Fatalf("not getting the corrent items %v", items)
}
if len(inventory.Previous) != 0 {
t.Fatalf("not getting the corrent inventory %v", inventory)
}
inventory.UpdateCurrent(newref)
items = inventory.Prune()
if len(items) != 1 {
t.Fatalf("not getting the corrent items %v", items)
}
if len(inventory.Previous) != 0 {
t.Fatalf("not getting the corrent inventory %v", inventory.Previous)
}
}

View File

@@ -75,11 +75,8 @@ func (kf *KunstructuredFactoryImpl) FromMap(
// MakeConfigMap returns an instance of Kunstructured for ConfigMap
func (kf *KunstructuredFactoryImpl) MakeConfigMap(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args *types.ConfigMapArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(
kvLdr, options).MakeConfigMap(args)
kvLdr ifc.KvLoader, args *types.ConfigMapArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(kvLdr).MakeConfigMap(args)
if err != nil {
return nil, err
}
@@ -88,11 +85,8 @@ func (kf *KunstructuredFactoryImpl) MakeConfigMap(
// MakeSecret returns an instance of Kunstructured for Secret
func (kf *KunstructuredFactoryImpl) MakeSecret(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args *types.SecretArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(
kvLdr, options).MakeSecret(args)
kvLdr ifc.KvLoader, args *types.SecretArgs) (ifc.Kunstructured, error) {
o, err := configmapandsecret.NewFactory(kvLdr).MakeSecret(args)
if err != nil {
return nil, err
}

View File

@@ -35,37 +35,46 @@ const (
// Domain from which kustomize code is imported, for locating
// plugin source code under $GOPATH when GOPATH is defined.
DomainName = "sigs.k8s.io"
// Injected into plugin paths when plugins are disabled.
// Provides a clue in flows that shouldn't happen.
NoPluginHomeSentinal = "/No/non-builtin/plugins!"
)
func EnabledPluginConfig() (*types.PluginConfig, error) {
func EnabledPluginConfig(b types.BuiltinPluginLoadingOptions) (*types.PluginConfig, error) {
dir, err := DefaultAbsPluginHome(filesys.MakeFsOnDisk())
if err != nil {
return nil, err
}
return MakePluginConfig(types.PluginRestrictionsNone, dir), nil
return MakePluginConfig(types.PluginRestrictionsNone, b, dir), nil
}
func DisabledPluginConfig() *types.PluginConfig {
return MakePluginConfig(
types.PluginRestrictionsBuiltinsOnly, NoPluginHomeSentinal)
types.PluginRestrictionsBuiltinsOnly,
types.BploUseStaticallyLinked,
NoPluginHomeSentinal)
}
func MakePluginConfig(
pr types.PluginRestrictions, home string) *types.PluginConfig {
pr types.PluginRestrictions,
b types.BuiltinPluginLoadingOptions,
home string) *types.PluginConfig {
return &types.PluginConfig{
PluginRestrictions: pr,
AbsPluginHome: home,
BpLoadingOptions: b,
}
}
// Use an obviously erroneous path, in case it's accidentally used.
const NoPluginHomeSentinal = "/no/non-builtin/plugins!"
type NotedFunc struct {
Note string
F func() string
}
// DefaultAbsPluginHome returns the absolute path in the given file
// system to first directory that looks like a good candidate for
// the home of kustomize plugins.
func DefaultAbsPluginHome(fSys filesys.FileSystem) (string, error) {
return FirstDirThatExistsElseError(
"plugin home directory", fSys, []NotedFunc{

View File

@@ -154,9 +154,8 @@ LEGUME=chickpea
`)
th.WriteF("/app/overlay/configmap/dummy.txt",
`Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
`)
th.WriteF("/app/overlay/deployment/deployment.yaml", `
apiVersion: apps/v1
@@ -293,11 +292,8 @@ metadata:
---
apiVersion: v1
data:
nonsense: |
Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
nonsense: "Lorem ipsum dolor sit amet, consectetur\nadipiscing elit, sed do eiusmod
tempor\nincididunt ut labore et dolore magna aliqua. \n"
kind: ConfigMap
metadata:
annotations:
@@ -306,6 +302,6 @@ metadata:
app: mungebot
org: kubernetes
repo: test-infra
name: test-infra-app-config-hh272bg5d4
name: test-infra-app-config-f462h769f9
`)
}

View File

@@ -143,7 +143,8 @@ apiVersion: builtin
kind: ConfigMapGenerator
metadata:
name: my-config
disableNameSuffixHash: true
options:
disableNameSuffixHash: true
literals:
- MY_ENV=foo
`)

View File

@@ -12,10 +12,12 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func findSecret(m resmap.ResMap) *resource.Resource {
func findSecret(m resmap.ResMap, prefix string) *resource.Resource {
for _, r := range m.Resources() {
if r.OrgId().Kind == "Secret" {
return r
if prefix == "" || strings.HasPrefix(r.GetName(), prefix) {
return r
}
}
}
return nil
@@ -77,7 +79,7 @@ metadata:
m := th.Run("/whatever", th.MakeDefaultOptions())
secret := findSecret(m)
secret := findSecret(m, "")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
@@ -90,7 +92,7 @@ metadata:
"disableNameSuffixHash: false",
"disableNameSuffixHash: true", -1))
m = th.Run("/whatever", th.MakeDefaultOptions())
secret = findSecret(m)
secret = findSecret(m, "")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
@@ -98,3 +100,47 @@ metadata:
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
}
func TestDisableNameSuffixHashPerObject(t *testing.T) {
th := kusttest_test.MakeHarness(t)
const kustomizationContent = `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
generatorOptions:
disableNameSuffixHash: false
secretGenerator:
- name: nohash
options:
disableNameSuffixHash: true
literals:
- DB_USERNAME=admin
- DB_PASSWORD=somepw
type: Opaque
- name: yeshash
options:
disableNameSuffixHash: false
literals:
- DB_USERNAME=admin
- DB_PASSWORD=somepw
type: Opaque
`
th.WriteK("/whatever", kustomizationContent)
m := th.Run("/whatever", th.MakeDefaultOptions())
secret := findSecret(m, "nohash")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "nohash" {
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
secret = findSecret(m, "yeshash")
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "yeshash-mcgcmdcm69" {
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
}

View File

@@ -71,11 +71,7 @@ func (b *Kustomizer) Run(path string) (resmap.ResMap, error) {
return nil, err
}
var m resmap.ResMap
if b.options.DoPrune {
m, err = kt.MakePruneConfigMap()
} else {
m, err = kt.MakeCustomizedResMap()
}
m, err = kt.MakeCustomizedResMap()
if err != nil {
return nil, err
}

View File

@@ -0,0 +1,110 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func makeCommonFileForMergeEnvFromTest(th kusttest_test.Harness) {
th.WriteF("/app/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- name: nginx
image: image1
envFrom:
- configMapRef:
name: some-config
- configMapRef:
name: more-config
`)
}
// When patching, `envFrom` should merge the list instead of replacing it.
func TestMergeEnvFrom(t *testing.T) {
th := kusttest_test.MakeHarness(t)
makeCommonFileForMergeEnvFromTest(th)
th.WriteK("/app", `
resources:
- deployment.yaml
patchesStrategicMerge:
- |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- name: nginx
envFrom:
- configMapRef:
name: another-config
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- envFrom:
- configMapRef:
name: another-config
image: image1
name: nginx
`)
}
func TestMergeEnvFromViaJsonInline(t *testing.T) {
th := kusttest_test.MakeHarness(t)
makeCommonFileForMergeEnvFromTest(th)
th.WriteK("app", `
resources:
- deployment.yaml
patches:
- target:
kind: Deployment
name: nginx
patch: |-
- op: add
path: /spec/template/spec/containers/0/envFrom/-
value:
configMapRef:
name: another-config
`)
m := th.Run("app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- envFrom:
- configMapRef:
name: some-config
- configMapRef:
name: more-config
- configMapRef:
name: another-config
image: image1
name: nginx
`)
}

View File

@@ -1,163 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func TestPruneConfigMap(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
resources:
- deployment.yaml
- service.yaml
- secret.yaml
inventory:
type: ConfigMap
configMap:
name: haha
namespace: default
namePrefix: my-
namespace: default
`)
th.WriteF("/app/base/deployment.yaml", `
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: mysql
labels:
app: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: pass
key: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
emptyDir: {}
`)
th.WriteF("/app/base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: mmmysql
labels:
app: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
`)
th.WriteF("/app/base/secret.yaml", `
apiVersion: v1
kind: Secret
metadata:
name: pass
type: Opaque
data:
# Default password is "admin".
password: YWRtaW4=
username: jingfang
`)
m := th.Run("/app/base", th.MakeDefaultOptions())
//nolint
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
metadata:
labels:
app: mysql
name: my-mysql
namespace: default
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: my-pass
image: mysql:5.6
name: mysql
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-persistent-storage
volumes:
- emptyDir: {}
name: mysql-persistent-storage
---
apiVersion: v1
kind: Service
metadata:
labels:
app: mysql
name: my-mmmysql
namespace: default
spec:
ports:
- port: 3306
selector:
app: mysql
---
apiVersion: v1
data:
password: YWRtaW4=
username: jingfang
kind: Secret
metadata:
name: my-pass
namespace: default
type: Opaque
---
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
kustomize.config.k8s.io/Inventory: '{"current":{"apps_v1beta2_Deployment|default|my-mysql":null,"~G_v1_Secret|default|my-pass":[{"group":"apps","version":"v1beta2","kind":"Deployment","name":"my-mysql","namespace":"default"}],"~G_v1_Service|default|my-mmmysql":null}}'
kustomize.config.k8s.io/InventoryHash: kd67f7ht8t
name: haha
namespace: default
`)
}

View File

@@ -9,7 +9,6 @@ import (
"fmt"
"os"
"path"
"regexp"
"strings"
"unicode"
"unicode/utf8"
@@ -86,17 +85,11 @@ func (kvl *loader) keyValuesFromFileSources(sources []string) ([]types.Pair, err
if err != nil {
return nil, err
}
kvs = append(kvs, types.Pair{Key: k, Value: trimTrailingSpacesInLines(string(content))})
kvs = append(kvs, types.Pair{Key: k, Value: string(content)})
}
return kvs, nil
}
// trimTrailingSpacesInLines takes string with multiple lines and trims the trailing white spaces and tabs from each line.
func trimTrailingSpacesInLines(str string) string {
re := regexp.MustCompile(`[ \t]*\n`)
return re.ReplaceAllString(str, "\n")
}
func (kvl *loader) keyValuesFromEnvFiles(paths []string) ([]types.Pair, error) {
var kvs []types.Pair
for _, p := range paths {

View File

@@ -95,12 +95,3 @@ func TestKeyValuesFromFileSources(t *testing.T) {
}
}
}
func TestTrimTrailingSpacesInLines(t *testing.T) {
input := "\"fooKey\": \"fooValue\" \t\n \t\t \n\t\"barKey\": \"barValue\""
expected := "\"fooKey\": \"fooValue\"\n\n\t\"barKey\": \"barValue\""
res := trimTrailingSpacesInLines(input)
if !reflect.DeepEqual(res, expected) {
t.Errorf("Trim trailing spaces in lines should succeed, got: %s exptected: %s", res, expected)
}
}

View File

@@ -66,12 +66,10 @@ func (rmF *Factory) NewResMapFromBytes(b []byte) (ResMap, error) {
// NewResMapFromConfigMapArgs returns a Resource slice given
// a configmap metadata slice from kustomization file.
func (rmF *Factory) NewResMapFromConfigMapArgs(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
argList []types.ConfigMapArgs) (ResMap, error) {
kvLdr ifc.KvLoader, argList []types.ConfigMapArgs) (ResMap, error) {
var resources []*resource.Resource
for _, args := range argList {
res, err := rmF.resF.MakeConfigMap(kvLdr, options, &args)
res, err := rmF.resF.MakeConfigMap(kvLdr, &args)
if err != nil {
return nil, errors.Wrap(err, "NewResMapFromConfigMapArgs")
}
@@ -81,10 +79,8 @@ func (rmF *Factory) NewResMapFromConfigMapArgs(
}
func (rmF *Factory) FromConfigMapArgs(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args types.ConfigMapArgs) (ResMap, error) {
res, err := rmF.resF.MakeConfigMap(kvLdr, options, &args)
kvLdr ifc.KvLoader, args types.ConfigMapArgs) (ResMap, error) {
res, err := rmF.resF.MakeConfigMap(kvLdr, &args)
if err != nil {
return nil, err
}
@@ -94,12 +90,10 @@ func (rmF *Factory) FromConfigMapArgs(
// NewResMapFromSecretArgs takes a SecretArgs slice, generates
// secrets from each entry, and accumulates them in a ResMap.
func (rmF *Factory) NewResMapFromSecretArgs(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
argsList []types.SecretArgs) (ResMap, error) {
kvLdr ifc.KvLoader, argsList []types.SecretArgs) (ResMap, error) {
var resources []*resource.Resource
for _, args := range argsList {
res, err := rmF.resF.MakeSecret(kvLdr, options, &args)
res, err := rmF.resF.MakeSecret(kvLdr, &args)
if err != nil {
return nil, errors.Wrap(err, "NewResMapFromSecretArgs")
}
@@ -109,10 +103,8 @@ func (rmF *Factory) NewResMapFromSecretArgs(
}
func (rmF *Factory) FromSecretArgs(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args types.SecretArgs) (ResMap, error) {
res, err := rmF.resF.MakeSecret(kvLdr, options, &args)
kvLdr ifc.KvLoader, args types.SecretArgs) (ResMap, error) {
res, err := rmF.resF.MakeSecret(kvLdr, &args)
if err != nil {
return nil, err
}

View File

@@ -227,7 +227,7 @@ BAR=baz
t.Fatalf("error adding file '%s': %v\n", tc.filepath, fErr)
}
}
r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, nil, tc.input)
r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
@@ -258,7 +258,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
actual, err := rmF.NewResMapFromSecretArgs(
kv.NewLoader(
loader.NewFileLoaderAtRoot(fSys),
valtest_test.MakeFakeValidator()), nil, secrets)
valtest_test.MakeFakeValidator()), secrets)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

View File

@@ -826,7 +826,7 @@ func makeMap1() ResMap {
},
}, &types.GeneratorArgs{
Behavior: "create",
}, nil))
}))
}
func makeMap2(b types.GenerationBehavior) ResMap {
@@ -844,7 +844,7 @@ func makeMap2(b types.GenerationBehavior) ResMap {
},
}, &types.GeneratorArgs{
Behavior: b.String(),
}, nil))
}))
}
func TestAbsorbAll(t *testing.T) {
@@ -864,7 +864,7 @@ func TestAbsorbAll(t *testing.T) {
},
}, &types.GeneratorArgs{
Behavior: "create",
}, nil))
}))
w := makeMap1()
if err := w.AbsorbAll(makeMap2(types.BehaviorMerge)); err != nil {
t.Fatalf("unexpected error: %v", err)

View File

@@ -50,8 +50,8 @@ func (rf *Factory) FromMapWithNamespaceAndName(ns string, n string, m map[string
// FromMapAndOption returns a new instance of Resource with given options.
func (rf *Factory) FromMapAndOption(
m map[string]interface{}, args *types.GeneratorArgs, option *types.GeneratorOptions) *Resource {
return rf.makeOne(rf.kf.FromMap(m), types.NewGenArgs(args, option))
m map[string]interface{}, args *types.GeneratorArgs) *Resource {
return rf.makeOne(rf.kf.FromMap(m), types.NewGenArgs(args))
}
// FromKunstructured returns a new instance of Resource.
@@ -66,7 +66,7 @@ func (rf *Factory) makeOne(
log.Fatal("unstruct ifc must not be null")
}
if o == nil {
o = types.NewGenArgs(nil, nil)
o = types.NewGenArgs(nil)
}
r := &Resource{
Kunstructured: u,
@@ -147,33 +147,19 @@ func (rf *Factory) SliceFromBytes(in []byte) ([]*Resource, error) {
}
// MakeConfigMap makes an instance of Resource for ConfigMap
func (rf *Factory) MakeConfigMap(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args *types.ConfigMapArgs) (*Resource, error) {
u, err := rf.kf.MakeConfigMap(kvLdr, options, args)
func (rf *Factory) MakeConfigMap(kvLdr ifc.KvLoader, args *types.ConfigMapArgs) (*Resource, error) {
u, err := rf.kf.MakeConfigMap(kvLdr, args)
if err != nil {
return nil, err
}
return rf.makeOne(
u,
types.NewGenArgs(
&types.GeneratorArgs{Behavior: args.Behavior},
options)), nil
return rf.makeOne(u, types.NewGenArgs(&args.GeneratorArgs)), nil
}
// MakeSecret makes an instance of Resource for Secret
func (rf *Factory) MakeSecret(
kvLdr ifc.KvLoader,
options *types.GeneratorOptions,
args *types.SecretArgs) (*Resource, error) {
u, err := rf.kf.MakeSecret(kvLdr, options, args)
func (rf *Factory) MakeSecret(kvLdr ifc.KvLoader, args *types.SecretArgs) (*Resource, error) {
u, err := rf.kf.MakeSecret(kvLdr, args)
if err != nil {
return nil, err
}
return rf.makeOne(
u,
types.NewGenArgs(
&types.GeneratorArgs{Behavior: args.Behavior},
options)), nil
return rf.makeOne(u, types.NewGenArgs(&args.GeneratorArgs)), nil
}

View File

@@ -70,7 +70,7 @@ func (th Harness) MakeOptionsPluginsDisabled() krusty.Options {
// Enables use of non-builtin plugins.
func (th Harness) MakeOptionsPluginsEnabled() krusty.Options {
c, err := konfig.EnabledPluginConfig()
c, err := konfig.EnabledPluginConfig(types.BploLoadFromFileSys)
if err != nil {
if strings.Contains(err.Error(), "unable to find plugin root") {
th.t.Log(

View File

@@ -19,38 +19,50 @@ import (
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// HarnessEnhanced manages a full plugin environment for tests.
type HarnessEnhanced struct {
// An instance of *testing.T, and a filesystem (likely in-memory)
// for loading test data - plugin config, resources to transform, etc.
Harness
// plugintestEnv holds the plugin compiler and data needed to
// create compilation sub-processes.
pte *pluginTestEnv
rf *resmap.Factory
// rf creates Resources from byte streams.
rf *resmap.Factory
// A file loader using the Harness.fSys to read test data.
ldr ifc.Loader
pl *pLdr.Loader
// A plugin loader that loads plugins from a (real) file system.
pl *pLdr.Loader
}
func MakeEnhancedHarness(t *testing.T) *HarnessEnhanced {
pte := newPluginTestEnv(t).set()
pc, err := konfig.EnabledPluginConfig()
pc, err := konfig.EnabledPluginConfig(types.BploLoadFromFileSys)
if err != nil {
t.Fatal(err)
}
fSys := filesys.MakeFsInMemory()
rf := resmap.NewFactory(
resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()),
transformer.NewFactoryImpl())
result := &HarnessEnhanced{
Harness: Harness{t: t, fSys: fSys},
Harness: MakeHarness(t),
pte: pte,
rf: rf,
pl: pLdr.NewLoader(pc, rf)}
// Point the file loader to the root ('/') of the in-memory file system.
result.ResetLoaderRoot(filesys.Separator)
return result
@@ -60,21 +72,23 @@ func (th *HarnessEnhanced) Reset() {
th.pte.reset()
}
func (th *HarnessEnhanced) PrepBuiltin(k string) *HarnessEnhanced {
return th.BuildGoPlugin(konfig.BuiltinPluginPackage, "", k)
}
func (th *HarnessEnhanced) BuildGoPlugin(g, v, k string) *HarnessEnhanced {
th.pte.buildGoPlugin(g, v, k)
th.pte.prepareGoPlugin(g, v, k)
return th
}
func (th *HarnessEnhanced) PrepExecPlugin(g, v, k string) *HarnessEnhanced {
th.pte.prepExecPlugin(g, v, k)
return th
}
func (th *HarnessEnhanced) PrepBuiltin(k string) *HarnessEnhanced {
th.pte.buildGoPlugin(konfig.BuiltinPluginPackage, "", k)
th.pte.prepareExecPlugin(g, v, k)
return th
}
// ResetLoaderRoot interprets its argument as an absolute directory path.
// It creates the directory, and creates the harness's file loader
// rooted in that directory.
func (th *HarnessEnhanced) ResetLoaderRoot(root string) {
if err := th.fSys.Mkdir(root); err != nil {
th.t.Fatal(err)
@@ -137,7 +151,6 @@ func toggleYamlSupportField(config string, yamlSupport bool) (string, error) {
Reader: bytes.NewBufferString(config),
Writer: &out,
}
err := kio.Pipeline{
Inputs: []kio.Reader{&rw},
Filters: []kio.Filter{

View File

@@ -4,11 +4,7 @@
package kusttest_test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
@@ -16,17 +12,14 @@ import (
"sigs.k8s.io/kustomize/api/konfig"
)
// pluginTestEnv manages plugins for tests.
// It manages a Go plugin compiler,
// makes and removes a temporary working directory,
// and sets/resets shell env vars as needed.
// pluginTestEnv manages compiling plugins for tests.
// It manages a Go plugin compiler, and sets/resets shell env vars as needed.
type pluginTestEnv struct {
t *testing.T
compiler *compiler.Compiler
srcRoot string
workDir string
oldXdg string
wasSet bool
t *testing.T
compiler *compiler.Compiler
pluginRoot string
oldXdg string
wasSet bool
}
// newPluginTestEnv returns a new instance of pluginTestEnv.
@@ -39,76 +32,44 @@ func newPluginTestEnv(t *testing.T) *pluginTestEnv {
// plugin code - this FileSystem has nothing to do with
// the FileSystem used for loading config yaml in the tests.
func (x *pluginTestEnv) set() *pluginTestEnv {
x.createWorkDir()
var err error
x.srcRoot, err = compiler.DeterminePluginSrcRoot(filesys.MakeFsOnDisk())
x.pluginRoot, err = compiler.DeterminePluginSrcRoot(filesys.MakeFsOnDisk())
if err != nil {
x.t.Error(err)
}
x.compiler = compiler.NewCompiler(x.srcRoot, x.workDir)
x.compiler = compiler.NewCompiler(x.pluginRoot)
x.setEnv()
return x
}
// reset restores the environment to pre-test state.
func (x *pluginTestEnv) reset() {
// Calling Cleanup forces recompilation in a test file with multiple
// calls to MakeEnhancedHarness - so leaving it out. Your .gitignore
// should ignore .so files anyway.
// x.compiler.Cleanup()
x.resetEnv()
x.removeWorkDir()
}
// buildGoPlugin compiles a Go plugin, leaving the newly
// created object code in the right place - a temporary
// working directory pointed to by KustomizePluginHomeEnv.
// This avoids overwriting anything the user/developer has
// otherwise created.
func (x *pluginTestEnv) buildGoPlugin(g, v, k string) {
err := x.compiler.Compile(g, v, k)
// prepareGoPlugin compiles a Go plugin, leaving the newly
// created object code alongside the src code.
func (x *pluginTestEnv) prepareGoPlugin(g, v, k string) {
x.compiler.SetGVK(g, v, k)
err := x.compiler.Compile()
if err != nil {
x.t.Errorf("compile failed: %v", err)
}
}
// prepExecPlugin copies an exec plugin from it's
// home in the discovered srcRoot to the same temp
// directory where Go plugin object code is placed.
// Kustomize (and its tests) expect to find plugins
// (Go or Exec) in the same spot, and since the test
// framework is compiling Go plugins to a temp dir,
// it must likewise copy Exec plugins to that same
// temp dir.
func (x *pluginTestEnv) prepExecPlugin(g, v, k string) {
lowK := strings.ToLower(k)
src := filepath.Join(x.srcRoot, g, v, lowK, k)
tmp := filepath.Join(x.workDir, g, v, lowK, k)
if err := os.MkdirAll(filepath.Dir(tmp), 0755); err != nil {
x.t.Errorf("error making directory: %s", filepath.Dir(tmp))
}
cmd := exec.Command("cp", src, tmp)
cmd.Env = os.Environ()
if err := cmd.Run(); err != nil {
x.t.Errorf("error copying %s to %s: %v", src, tmp, err)
}
}
func (x *pluginTestEnv) createWorkDir() {
var err error
x.workDir, err = ioutil.TempDir("", "kustomize-plugin-tests")
if err != nil {
x.t.Errorf("failed to make work dir: %v", err)
}
}
func (x *pluginTestEnv) removeWorkDir() {
err := os.RemoveAll(x.workDir)
if err != nil {
x.t.Errorf(
"removing work dir: %s %v", x.workDir, err)
}
func (x *pluginTestEnv) prepareExecPlugin(_, _, _ string) {
// Do nothing. At one point this method
// copied the exec plugin directory to a temp dir
// and ran it from there. Left as a hook.
}
func (x *pluginTestEnv) setEnv() {
x.oldXdg, x.wasSet = os.LookupEnv(konfig.KustomizePluginHomeEnv)
os.Setenv(konfig.KustomizePluginHomeEnv, x.workDir)
os.Setenv(konfig.KustomizePluginHomeEnv, x.pluginRoot)
}
func (x *pluginTestEnv) resetEnv() {

View File

@@ -1,64 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package transform
import (
"errors"
"fmt"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
)
// mapTransformer applies a string->string map to fieldSpecs.
type mapTransformer struct {
m map[string]string
fieldSpecs []types.FieldSpec
}
var _ resmap.Transformer = &mapTransformer{}
// NewMapTransformer construct a mapTransformer.
func NewMapTransformer(
pc []types.FieldSpec, m map[string]string) (resmap.Transformer, error) {
if m == nil {
return newNoOpTransformer(), nil
}
if pc == nil {
return nil, errors.New("fieldSpecs is not expected to be nil")
}
return &mapTransformer{fieldSpecs: pc, m: m}, nil
}
// Transform apply each <key, value> pair in the mapTransformer to the
// fields specified in mapTransformer.
func (o *mapTransformer) Transform(m resmap.ResMap) error {
for _, r := range m.Resources() {
for _, path := range o.fieldSpecs {
if !r.OrgId().IsSelected(&path.Gvk) {
continue
}
err := MutateField(
r.Map(), path.PathSlice(),
path.CreateIfNotPresent, o.addMap)
if err != nil {
return err
}
}
}
return nil
}
func (o *mapTransformer) addMap(in interface{}) (interface{}, error) {
m, ok := in.(map[string]interface{})
if in == nil {
m = map[string]interface{}{}
} else if !ok {
return nil, fmt.Errorf("%#v is expected to be %T", in, m)
}
for k, v := range o.m {
m[k] = v
}
return m, nil
}

View File

@@ -1,570 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package transform_test
import (
"testing"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/resource"
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
. "sigs.k8s.io/kustomize/api/transform"
)
var resourceFactory = resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
func TestLabelsRun(t *testing.T) {
m := resmaptest_test.NewRmBuilder(t, resourceFactory).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
},
}).
Add(map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "svc1",
},
"spec": map[string]interface{}{
"ports": []interface{}{
map[string]interface{}{
"name": "port1",
"port": "12345",
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "batch/v1",
"kind": "Job",
"metadata": map[string]interface{}{
"name": "job1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "batch/v1",
"kind": "Job",
"metadata": map[string]interface{}{
"name": "job2",
},
"spec": map[string]interface{}{
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"old-label": "old-value",
},
},
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "batch/v1beta1",
"kind": "CronJob",
"metadata": map[string]interface{}{
"name": "cronjob1",
},
"spec": map[string]interface{}{
"schedule": "* 23 * * *",
"jobTemplate": map[string]interface{}{
"spec": map[string]interface{}{
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "batch/v1beta1",
"kind": "CronJob",
"metadata": map[string]interface{}{
"name": "cronjob2",
},
"spec": map[string]interface{}{
"schedule": "* 23 * * *",
"jobTemplate": map[string]interface{}{
"spec": map[string]interface{}{
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"old-label": "old-value",
},
},
"template": map[string]interface{}{
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
},
},
}).ResMap()
expected := resmaptest_test.NewRmBuilder(t, resourceFactory).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
}).
Add(map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "svc1",
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"ports": []interface{}{
map[string]interface{}{
"name": "port1",
"port": "12345",
},
},
"selector": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
}).
Add(map[string]interface{}{
"apiVersion": "batch/v1",
"kind": "Job",
"metadata": map[string]interface{}{
"name": "job1",
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "batch/v1",
"kind": "Job",
"metadata": map[string]interface{}{
"name": "job2",
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
"old-label": "old-value",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "batch/v1beta1",
"kind": "CronJob",
"metadata": map[string]interface{}{
"name": "cronjob1",
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"schedule": "* 23 * * *",
"jobTemplate": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "batch/v1beta1",
"kind": "CronJob",
"metadata": map[string]interface{}{
"name": "cronjob2",
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"schedule": "* 23 * * *",
"jobTemplate": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"old-label": "old-value",
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"label-key1": "label-value1",
"label-key2": "label-value2",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
},
},
}).ResMap()
lt, err := NewMapTransformer(
builtinconfig.MakeDefaultConfig().CommonLabels,
map[string]string{"label-key1": "label-value1", "label-key2": "label-value2"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = lt.Transform(m)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
}
}
func TestAnnotationsRun(t *testing.T) {
m := resmaptest_test.NewRmBuilder(t, resourceFactory).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
},
}).
Add(map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "svc1",
},
"spec": map[string]interface{}{
"ports": []interface{}{
map[string]interface{}{
"name": "port1",
"port": "12345",
},
},
},
}).ResMap()
expected := resmaptest_test.NewRmBuilder(t, resourceFactory).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
"annotations": map[string]interface{}{
"anno-key1": "anno-value1",
"anno-key2": "anno-value2",
},
},
}).
Add(map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
"annotations": map[string]interface{}{
"anno-key1": "anno-value1",
"anno-key2": "anno-value2",
},
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"anno-key1": "anno-value1",
"anno-key2": "anno-value2",
},
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "svc1",
"annotations": map[string]interface{}{
"anno-key1": "anno-value1",
"anno-key2": "anno-value2",
},
},
"spec": map[string]interface{}{
"ports": []interface{}{
map[string]interface{}{
"name": "port1",
"port": "12345",
},
},
},
}).ResMap()
at, err := NewMapTransformer(
builtinconfig.MakeDefaultConfig().CommonAnnotations,
map[string]string{"anno-key1": "anno-value1", "anno-key2": "anno-value2"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = at.Transform(m)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
}
}
func TestAnnotationsRunWithNullValue(t *testing.T) {
m := resmaptest_test.NewRmBuilder(t, resourceFactory).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
"annotations": nil,
},
}).ResMap()
expected := resmaptest_test.NewRmBuilder(t, resourceFactory).
Add(map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
"annotations": map[string]interface{}{
"anno-key1": "anno-value1",
"anno-key2": "anno-value2",
},
},
}).ResMap()
at, err := NewMapTransformer(
builtinconfig.MakeDefaultConfig().CommonAnnotations,
map[string]string{"anno-key1": "anno-value1", "anno-key2": "anno-value2"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = at.Transform(m)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err = expected.ErrorIfNotEqualLists(m); err != nil {
t.Fatalf("actual doesn't match expected: %v", err)
}
}

View File

@@ -1,21 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package transform
import "sigs.k8s.io/kustomize/api/resmap"
// noOpTransformer contains a no-op transformer.
type noOpTransformer struct{}
var _ resmap.Transformer = &noOpTransformer{}
// newNoOpTransformer constructs a noOpTransformer.
func newNoOpTransformer() resmap.Transformer {
return &noOpTransformer{}
}
// Transform does nothing.
func (o *noOpTransformer) Transform(_ resmap.ResMap) error {
return nil
}

View File

@@ -1,12 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package types
//go:generate stringer -type=GarbagePolicy
type GarbagePolicy int
const (
GarbageIgnore GarbagePolicy = iota + 1
GarbageCollect
)

View File

@@ -1,25 +0,0 @@
// Code generated by "stringer -type=GarbagePolicy"; DO NOT EDIT.
package types
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[GarbageIgnore-1]
_ = x[GarbageCollect-2]
}
const _GarbagePolicy_name = "GarbageIgnoreGarbageCollect"
var _GarbagePolicy_index = [...]uint8{0, 13, 27}
func (i GarbagePolicy) String() string {
i -= 1
if i < 0 || i >= GarbagePolicy(len(_GarbagePolicy_index)-1) {
return "GarbagePolicy(" + strconv.FormatInt(int64(i+1), 10) + ")"
}
return _GarbagePolicy_name[_GarbagePolicy_index[i]:_GarbagePolicy_index[i+1]]
}

View File

@@ -8,18 +8,14 @@ import (
"strings"
)
// GenArgs contains both GeneratorArgs and GeneratorOptions.
// GenArgs is a facade over GeneratorArgs, exposing a few readonly properties.
type GenArgs struct {
args *GeneratorArgs
opts *GeneratorOptions
}
// NewGenArgs returns a new object of GenArgs
func NewGenArgs(args *GeneratorArgs, opts *GeneratorOptions) *GenArgs {
return &GenArgs{
args: args,
opts: opts,
}
// NewGenArgs returns a new instance of GenArgs.
func NewGenArgs(args *GeneratorArgs) *GenArgs {
return &GenArgs{args: args}
}
func (g *GenArgs) String() string {
@@ -38,7 +34,7 @@ func (g *GenArgs) String() string {
// content hash should be appended to the name of the resource.
func (g *GenArgs) ShouldAddHashSuffixToName() bool {
return g.args != nil &&
(g.opts == nil || !g.opts.DisableNameSuffixHash)
(g.args.Options == nil || !g.args.Options.DisableNameSuffixHash)
}
// Behavior returns Behavior field of GeneratorArgs

View File

@@ -24,8 +24,10 @@ func TestGenArgs_String(t *testing.T) {
},
{
ga: NewGenArgs(
&GeneratorArgs{Behavior: "merge"},
&GeneratorOptions{DisableNameSuffixHash: false}),
&GeneratorArgs{
Behavior: "merge",
Options: &GeneratorOptions{DisableNameSuffixHash: false},
}),
expected: "{nsfx:true,beh:merge}",
},
}

View File

@@ -22,6 +22,6 @@ type GeneratorArgs struct {
// KvPairSources for the generator.
KvPairSources `json:",inline,omitempty" yaml:",inline,omitempty"`
// GeneratorOptions modify this generator
GeneratorOptions *GeneratorOptions `json:"generatorOptions,omitempty" yaml:"generatorOptions,omitempty"`
// Local overrides to global generatorOptions field.
Options *GeneratorOptions `json:"options,omitempty" yaml:"options,omitempty"`
}

View File

@@ -16,3 +16,55 @@ type GeneratorOptions struct {
// resource contents.
DisableNameSuffixHash bool `json:"disableNameSuffixHash,omitempty" yaml:"disableNameSuffixHash,omitempty"`
}
// MergeGlobalOptionsIntoLocal merges two instances of GeneratorOptions.
// Values in the first 'local' argument cannot be overridden by the second
// 'global' argument, except in the case of booleans.
//
// With booleans, there's no way to distinguish an 'intentional'
// false from 'default' false. So the rule is, if the global value
// of the value of a boolean is true, i.e. disable, it trumps the
// local value. If the global value is false, then the local value is
// respected. Bottom line: a local false cannot override a global true.
//
// boolean fields are always a bad idea; should always use enums instead.
func MergeGlobalOptionsIntoLocal(
localOpts *GeneratorOptions,
globalOpts *GeneratorOptions) *GeneratorOptions {
if globalOpts == nil {
return localOpts
}
if localOpts == nil {
localOpts = &GeneratorOptions{}
}
overrideMap(&localOpts.Labels, globalOpts.Labels)
overrideMap(&localOpts.Annotations, globalOpts.Annotations)
if globalOpts.DisableNameSuffixHash {
localOpts.DisableNameSuffixHash = true
}
return localOpts
}
func overrideMap(localMap *map[string]string, globalMap map[string]string) {
if *localMap == nil {
if globalMap != nil {
*localMap = CopyMap(globalMap)
}
return
}
for k, v := range globalMap {
_, ok := (*localMap)[k]
if !ok {
(*localMap)[k] = v
}
}
}
// CopyMap copies a map.
func CopyMap(in map[string]string) map[string]string {
out := make(map[string]string)
for k, v := range in {
out[k] = v
}
return out
}

View File

@@ -0,0 +1,125 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package types_test
import (
"reflect"
"testing"
. "sigs.k8s.io/kustomize/api/types"
)
func TestMergeGlobalOptionsIntoLocal(t *testing.T) {
tests := []struct {
name string
local *GeneratorOptions
global *GeneratorOptions
expected *GeneratorOptions
}{
{
name: "everything nil",
local: nil,
global: nil,
expected: nil,
},
{
name: "nil global",
local: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
},
global: nil,
expected: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
DisableNameSuffixHash: false,
},
},
{
name: "nil local",
local: nil,
global: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
},
expected: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
DisableNameSuffixHash: false,
},
},
{
name: "global doesn't damage local",
local: &GeneratorOptions{
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{
"fruit": "apple"},
},
global: &GeneratorOptions{
Labels: map[string]string{
"pet": "cat",
"simpson": "homer",
},
Annotations: map[string]string{
"fruit": "peach",
"tesla": "Y",
},
},
expected: &GeneratorOptions{
Labels: map[string]string{
"pet": "dog",
"simpson": "homer",
},
Annotations: map[string]string{
"fruit": "apple",
"tesla": "Y",
},
DisableNameSuffixHash: false,
},
},
{
name: "global disable trumps local",
local: &GeneratorOptions{
DisableNameSuffixHash: false,
},
global: &GeneratorOptions{
DisableNameSuffixHash: true,
},
expected: &GeneratorOptions{
DisableNameSuffixHash: true,
},
},
{
name: "local disable works",
local: &GeneratorOptions{
DisableNameSuffixHash: true,
},
global: &GeneratorOptions{
DisableNameSuffixHash: false,
},
expected: &GeneratorOptions{
DisableNameSuffixHash: true,
},
},
{
name: "everyone wants disable",
local: &GeneratorOptions{
DisableNameSuffixHash: true,
},
global: &GeneratorOptions{
DisableNameSuffixHash: true,
},
expected: &GeneratorOptions{
DisableNameSuffixHash: true,
},
},
}
for _, tc := range tests {
actual := MergeGlobalOptionsIntoLocal(tc.local, tc.global)
if !reflect.DeepEqual(tc.expected, actual) {
t.Fatalf("%s annotations: Expected '%v', got '%v'",
tc.name, tc.expected, *actual)
}
}
}

View File

@@ -4,8 +4,9 @@
package types
const (
KustomizationVersion = "kustomize.config.k8s.io/v1beta1"
KustomizationKind = "Kustomization"
KustomizationVersion = "kustomize.config.k8s.io/v1beta1"
KustomizationKind = "Kustomization"
MetadataNamespacePath = "metadata/namespace"
)
// Kustomization holds the information needed to generate customized k8s api resources.

View File

@@ -10,22 +10,23 @@ type PluginConfig struct {
// containing the fields 'apiVersion' and 'kind', e.g.
// apiVersion: apps/v1
// kind: Deployment
// When kustomize reads a plugin configuration file (as as result
// of seeing the file name in the 'generators:' or 'transformers:'
// field in a kustomization file), it must then locate the plugin
// code (Go plugin or exec plugin).
// Every kustomize plugin (its code, its tests, supporting data
// kustomize reads plugin configuration data from a file path
// specified in the 'generators:' or 'transformers:' field of a
// kustomization file. kustomize must then use this data to both
// locate the plugin and configure it.
// Every kustomize plugin (its code, its tests, its supporting data
// files, etc.) must be housed in its own directory at
// ${AbsPluginHome}/${pluginApiVersion}/LOWERCASE(${pluginKind})
// where
// - ${AbsPluginHome} is an absolute path, defined below.
// - ${pluginApiVersion} is taken from the plugin config file.
// - ${pluginKind} is taken from the plugin config file.
// The value of AbsPluginHome can be any absolute path, but might
// default to $XDG_CONFIG_HOME/kustomize/plugin.
// The value of AbsPluginHome can be any absolute path.
AbsPluginHome string
// PluginRestrictions defines the plugin restriction state.
// See type for more information.
// PluginRestrictions distinguishes plugin restrictions.
PluginRestrictions PluginRestrictions
// BpLoadingOptions distinguishes builtin plugin behaviors.
BpLoadingOptions BuiltinPluginLoadingOptions
}

View File

@@ -26,3 +26,18 @@ const (
// No restrictions, do whatever you want.
PluginRestrictionsNone
)
// BuiltinPluginLoadingOptions distinguish ways in which builtin plugins are used.
//go:generate stringer -type=BuiltinPluginLoadingOptions
type BuiltinPluginLoadingOptions int
const (
BploUndefined BuiltinPluginLoadingOptions = iota
// Desired in production use for performance.
BploUseStaticallyLinked
// Desired in testing and development cycles where it's undesirable
// to generate static code.
BploLoadFromFileSys
)

View File

@@ -19,7 +19,7 @@ linters:
# - gochecknoinits
# - goconst
# - gocritic
- gocyclo
# - gocyclo
- gofmt
- goimports
# - golint

View File

@@ -32,7 +32,7 @@ lint:
$(GOBIN)/golangci-lint run ./...
test:
go test -cover ./...
go test -v -timeout 45m -cover ./...
vet:
go vet ./...

View File

@@ -77,8 +77,7 @@ An example using `v1/List` as input:
apiVersion: v1
kind: List
items:
spec:
- apiVersion: foo-corp.com/v1
- apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging

View File

@@ -4,13 +4,12 @@ go 1.13
require (
github.com/go-errors/errors v1.0.1
github.com/go-openapi/spec v0.19.5
github.com/olekukonko/tablewriter v0.0.4
github.com/posener/complete/v2 v2.0.1-alpha.12
github.com/spf13/cobra v0.0.5
github.com/spf13/cobra v1.0.0
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.10
)
replace sigs.k8s.io/kustomize/kyaml v0.0.0 => ../../kyaml

View File

@@ -1,6 +1,8 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
@@ -8,19 +10,29 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
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/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/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
@@ -28,8 +40,12 @@ github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
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/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-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
@@ -45,18 +61,31 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp
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-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 h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/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-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/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.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/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
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/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 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/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.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
@@ -66,10 +95,15 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
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.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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=
@@ -82,6 +116,7 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
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=
@@ -91,7 +126,9 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -101,6 +138,7 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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=
@@ -109,50 +147,84 @@ github.com/posener/complete/v2 v2.0.1-alpha.12 h1:0wvkuDfHb5vSZlNBYgpEH4XQHpF46M
github.com/posener/complete/v2 v2.0.1-alpha.12/go.mod h1://JlL91cS2JV7rOl6LVHrRqBXoBUecJu3ILQPgbJiMQ=
github.com/posener/script v1.0.4 h1:nSuXW5ZdmFnQIueLB2s0qvs4oNsUloM1Zydzh75v42w=
github.com/posener/script v1.0.4/go.mod h1:Rg3ijooqulo05aGLyGsHoLmIOUzHUVK19WVgrYBPU/E=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/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-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d h1:K6eOUihrFLdZjZnA4XlRp864fmWXv9YTIk7VPLhRacA=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
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.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/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
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/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.2.3-0.20181224173747-660f15d67dbb/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/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
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.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/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-20181114220301-adae6a3d119a/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-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
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/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/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/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/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/sys v0.0.0-20170830134202-bb24a47a89ea/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-20181205085412-a5c9d58dba9a/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -160,9 +232,18 @@ golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fq
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/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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
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=
@@ -170,7 +251,9 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
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.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=
@@ -179,11 +262,14 @@ 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=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
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.10 h1:ZZfBnA/kYa9ZxUFIgI9oq3pWKzzA1gGOKgU0Hv/NhVg=
sigs.k8s.io/kustomize/kyaml v0.1.10/go.mod h1:mPmeBSRy0LTMv6fSrYSoi2yIFNZVouGKDsTekE5kdhs=
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=

View File

@@ -4,11 +4,15 @@
package commands
import (
"github.com/go-openapi/spec"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/ext"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/setters"
"sigs.k8s.io/kustomize/kyaml/setters2"
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
)
@@ -86,12 +90,30 @@ func (r *CreateSetterRunner) preRunE(c *cobra.Command, args []string) error {
if setterVersion == "v2" {
var err 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
}
if err := openapi.AddSchemaFromFile(r.OpenAPIFile); err != nil {
return err
}
// check if substitution with same name exists and throw error
ref, err := spec.NewRef(setters2.DefinitionsPrefix + setters2.SubstitutionDefinitionPrefix + r.CreateSetter.Name)
if err != nil {
return err
}
subst, _ := openapi.Resolve(&ref)
// if substitution already exists with the input setter name, throw error
if subst != nil {
return errors.Errorf("substitution with name %s already exists, "+
"substitution and setter can't have same name", r.CreateSetter.Name)
}
r.CreateSetter.Description = r.Set.SetPartialField.Description
r.CreateSetter.SetBy = r.Set.SetPartialField.SetBy
r.CreateSetter.Type = r.Set.SetPartialField.Type
}
return nil
}

View File

@@ -22,8 +22,10 @@ func TestCreateSetterCommand(t *testing.T) {
input string
args []string
out string
inputOpenAPI string
expectedOpenAPI string
expectedResources string
err string
}{
{
name: "add replicas",
@@ -36,6 +38,10 @@ metadata:
spec:
replicas: 3
`,
inputOpenAPI: `
apiVersion: v1alpha1
kind: Example
`,
expectedOpenAPI: `
apiVersion: v1alpha1
kind: Example
@@ -58,6 +64,27 @@ spec:
replicas: 3 # {"$ref":"#/definitions/io.k8s.cli.setters.replicas"}
`,
},
{
name: "error if substitution with same name exists",
args: []string{"my-image", "3", "--description", "hello world", "--set-by", "me"},
inputOpenAPI: `
apiVersion: v1alpha1
kind: Example
openAPI:
definitions:
io.k8s.cli.substitutions.my-image:
x-k8s-cli:
substitution:
name: my-image
pattern: something/${my-image-setter}::${my-tag-setter}/nginxotherthing
values:
- marker: ${my-image-setter}
ref: '#/definitions/io.k8s.cli.setters.my-image-setter'
- marker: ${my-tag-setter}
ref: '#/definitions/io.k8s.cli.setters.my-tag-setter'
`,
err: "substitution with name my-image already exists, substitution and setter can't have same name",
},
}
for i := range tests {
test := tests[i]
@@ -71,10 +98,7 @@ spec:
t.FailNow()
}
defer os.Remove(f.Name())
err = ioutil.WriteFile(f.Name(), []byte(`
apiVersion: v1alpha1
kind: Example
`), 0600)
err = ioutil.WriteFile(f.Name(), []byte(test.inputOpenAPI), 0600)
if !assert.NoError(t, err) {
t.FailNow()
}
@@ -99,6 +123,14 @@ kind: Example
runner.Command.SetOut(out)
runner.Command.SetArgs(append([]string{r.Name()}, test.args...))
err = runner.Command.Execute()
if test.err != "" {
if !assert.NotNil(t, err) {
t.FailNow()
} else {
assert.Equal(t, err.Error(), test.err)
return
}
}
if !assert.NoError(t, err) {
t.FailNow()
}

View File

@@ -4,11 +4,15 @@
package commands
import (
"fmt"
"regexp"
"strings"
"github.com/go-openapi/spec"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/ext"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/openapi"
"sigs.k8s.io/kustomize/kyaml/setters2"
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
)
@@ -17,20 +21,19 @@ import (
func NewCreateSubstitutionRunner(parent string) *CreateSubstitutionRunner {
r := &CreateSubstitutionRunner{}
cs := &cobra.Command{
Use: "create-subst DIR NAME VALUE",
Args: cobra.ExactArgs(3),
Use: "create-subst DIR NAME",
Args: cobra.ExactArgs(2),
PreRunE: r.preRunE,
RunE: r.runE,
}
cs.Flags().StringVar(&r.CreateSubstitution.FieldName, "field", "",
"name of the field to set -- e.g. --field port")
"name of the field to set -- e.g. --field image")
cs.Flags().StringVar(&r.CreateSubstitution.FieldValue, "field-value", "",
"value of the field to create substitution for -- e.g. --field-value nginx:0.1.0")
cs.Flags().StringVar(&r.CreateSubstitution.Pattern, "pattern", "",
"substitution pattern")
cs.Flags().StringSliceVar(&r.Values, "value", []string{""},
"substitution values for the pattern. format is PATTERN_MARKER=SETTER_NAME"+
"where PATTERN_MARKER is the pattern substring to replace, and SETTER_NAME is the"+
"setter from which to take the replacement value.")
`substitution pattern -- e.g. --pattern \${my-image-setter}:\${my-tag-setter}`)
_ = cs.MarkFlagRequired("pattern")
_ = cs.MarkFlagRequired("field-value")
fixDocs(parent, cs)
r.Command = cs
return r
@@ -54,7 +57,6 @@ func (r *CreateSubstitutionRunner) runE(c *cobra.Command, args []string) error {
func (r *CreateSubstitutionRunner) preRunE(c *cobra.Command, args []string) error {
var err error
r.CreateSubstitution.Name = args[1]
r.CreateSubstitution.FieldValue = args[2]
if err != nil {
return err
}
@@ -64,16 +66,37 @@ func (r *CreateSubstitutionRunner) preRunE(c *cobra.Command, args []string) erro
return err
}
// parse the marker values
for i := range r.Values {
parts := strings.SplitN(r.Values[i], "=", 2)
if len(parts) < 2 {
return errors.Errorf("values must be specified as PATTERN_MARKER=SETTER_NAME")
}
ref := setters2.DefinitionsPrefix + setters2.SetterDefinitionPrefix + parts[1]
if err := openapi.AddSchemaFromFile(r.OpenAPIFile); err != nil {
return err
}
// check if setter with same name exists and throw error
ref, err := spec.NewRef(setters2.DefinitionsPrefix + setters2.SetterDefinitionPrefix + r.CreateSubstitution.Name)
if err != nil {
return err
}
setter, _ := openapi.Resolve(&ref)
// if setter already exists with input substitution name, throw error
if setter != nil {
return errors.Errorf(fmt.Sprintf("setter with name %s already exists, "+
"substitution and setter can't have same name", r.CreateSubstitution.Name))
}
// extract setter name tokens from pattern enclosed in ${}
re := regexp.MustCompile(`\$\{([^}]*)\}`)
markers := re.FindAll([]byte(r.CreateSubstitution.Pattern), -1)
if len(markers) == 0 {
return errors.Errorf("unable to find setter names in pattern, " +
"setter names must be enclosed in ${}")
}
for _, marker := range markers {
ref := setters2.DefinitionsPrefix + setters2.SetterDefinitionPrefix +
strings.TrimSuffix(strings.TrimPrefix(string(marker), "${"), "}")
r.CreateSubstitution.Values = append(
r.CreateSubstitution.Values,
setters2.Value{Marker: parts[0], Ref: ref},
setters2.Value{Marker: string(marker), Ref: ref},
)
}

View File

@@ -25,12 +25,12 @@ func TestCreateSubstitutionCommand(t *testing.T) {
out string
expectedOpenAPI string
expectedResources string
err string
}{
{
name: "substitution replicas",
args: []string{
"image", "nginx:1.7.9", "--pattern", "IMAGE:TAG",
"--value", "IMAGE=image", "--value", "TAG=tag"},
"my-image-subst", "--field-value", "nginx:1.7.9", "--pattern", "${my-image-setter}:${my-tag-setter}"},
input: `
apiVersion: apps/v1
kind: Deployment
@@ -51,15 +51,15 @@ apiVersion: v1alpha1
kind: Example
openAPI:
definitions:
io.k8s.cli.setters.image:
io.k8s.cli.setters.my-image-setter:
x-k8s-cli:
setter:
name: image
name: my-image-setter
value: "nginx"
io.k8s.cli.setters.tag:
io.k8s.cli.setters.my-tag-setter:
x-k8s-cli:
setter:
name: tag
name: my-tag-setter
value: "1.7.9"
`,
expectedOpenAPI: `
@@ -67,26 +67,26 @@ apiVersion: v1alpha1
kind: Example
openAPI:
definitions:
io.k8s.cli.setters.image:
io.k8s.cli.setters.my-image-setter:
x-k8s-cli:
setter:
name: image
name: my-image-setter
value: "nginx"
io.k8s.cli.setters.tag:
io.k8s.cli.setters.my-tag-setter:
x-k8s-cli:
setter:
name: tag
name: my-tag-setter
value: "1.7.9"
io.k8s.cli.substitutions.image:
io.k8s.cli.substitutions.my-image-subst:
x-k8s-cli:
substitution:
name: image
pattern: IMAGE:TAG
name: my-image-subst
pattern: ${my-image-setter}:${my-tag-setter}
values:
- marker: IMAGE
ref: '#/definitions/io.k8s.cli.setters.image'
- marker: TAG
ref: '#/definitions/io.k8s.cli.setters.tag'
- marker: ${my-image-setter}
ref: '#/definitions/io.k8s.cli.setters.my-image-setter'
- marker: ${my-tag-setter}
ref: '#/definitions/io.k8s.cli.setters.my-tag-setter'
`,
expectedResources: `
apiVersion: apps/v1
@@ -99,16 +99,32 @@ spec:
spec:
containers:
- name: nginx
image: nginx:1.7.9 # {"$ref":"#/definitions/io.k8s.cli.substitutions.image"}
image: nginx:1.7.9 # {"$ref":"#/definitions/io.k8s.cli.substitutions.my-image-subst"}
- name: sidecar
image: sidecar:1.7.9
`,
},
{
name: "error if setter with same name exists",
args: []string{
"my-image", "--field-value", "nginx:1.7.9", "--pattern", "${my-image-setter}:${my-tag-setter}"},
inputOpenAPI: `
apiVersion: v1alpha1
kind: Example
openAPI:
definitions:
io.k8s.cli.setters.my-image:
x-k8s-cli:
setter:
name: my-image
value: "nginx"
`,
err: "setter with name my-image already exists, substitution and setter can't have same name",
},
{
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"},
"my-image-subst", "--field-value", "something/nginx::1.7.9/nginxotherthing", "--pattern", "something/${my-image-setter}::${my-tag-setter}/nginxotherthing"},
input: `
apiVersion: apps/v1
kind: Deployment
@@ -133,26 +149,26 @@ apiVersion: v1alpha1
kind: Example
openAPI:
definitions:
io.k8s.cli.setters.image:
io.k8s.cli.setters.my-image-setter:
x-k8s-cli:
setter:
name: image
name: my-image-setter
value: nginx
io.k8s.cli.setters.tag:
io.k8s.cli.setters.my-tag-setter:
x-k8s-cli:
setter:
name: tag
name: my-tag-setter
value: 1.7.9
io.k8s.cli.substitutions.image:
io.k8s.cli.substitutions.my-image-subst:
x-k8s-cli:
substitution:
name: image
pattern: something/IMAGE::TAG/nginxotherthing
name: my-image-subst
pattern: something/${my-image-setter}::${my-tag-setter}/nginxotherthing
values:
- marker: IMAGE
ref: '#/definitions/io.k8s.cli.setters.image'
- marker: TAG
ref: '#/definitions/io.k8s.cli.setters.tag'
- marker: ${my-image-setter}
ref: '#/definitions/io.k8s.cli.setters.my-image-setter'
- marker: ${my-tag-setter}
ref: '#/definitions/io.k8s.cli.setters.my-tag-setter'
`,
expectedResources: `
apiVersion: apps/v1
@@ -165,7 +181,7 @@ spec:
spec:
containers:
- name: nginx
image: something/nginx::1.7.9/nginxotherthing # {"$ref":"#/definitions/io.k8s.cli.substitutions.image"}
image: something/nginx::1.7.9/nginxotherthing # {"$ref":"#/definitions/io.k8s.cli.substitutions.my-image-subst"}
- name: sidecar
image: sidecar:1.7.9
`,
@@ -208,6 +224,14 @@ spec:
runner.Command.SetOut(out)
runner.Command.SetArgs(append([]string{r.Name()}, test.args...))
err = runner.Command.Execute()
if test.err != "" {
if !assert.NotNil(t, err) {
t.FailNow()
}
assert.Equal(t, err.Error(), test.err)
return
}
if !assert.NoError(t, err) {
t.FailNow()
}

View File

@@ -59,42 +59,83 @@ func (r *ListSettersRunner) preRunE(c *cobra.Command, args []string) error {
func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error {
if setterVersion == "v2" {
// use setters v2
path, err := ext.GetOpenAPIFile(args)
if err != nil {
if err := r.ListSetters(c, args); err != nil {
return err
}
if err := r.List.List(path, args[0]); err != nil {
return err
}
table := newTable(c.OutOrStdout(), r.Markdown)
table.SetHeader([]string{"NAME", "VALUE", "SET BY", "DESCRIPTION", "COUNT"})
for i := range r.List.Setters {
s := r.List.Setters[i]
v := s.Value
// if the setter is for a list, populate the values
if len(s.ListValues) > 0 {
v = strings.Join(s.ListValues, ",")
v = fmt.Sprintf("[%s]", v)
}
table.Append([]string{
s.Name, v, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count)})
}
table.Render()
if len(r.List.Setters) == 0 {
// exit non-0 if no matching setters are found
if ExitOnError {
os.Exit(1)
}
}
return nil
return r.ListSubstitutions(c, args)
}
return handleError(c, lookup(r.Lookup, c, args))
}
func (r *ListSettersRunner) ListSetters(c *cobra.Command, args []string) error {
// use setters v2
path, err := ext.GetOpenAPIFile(args)
if err != nil {
return err
}
if err := r.List.ListSetters(path, args[0]); err != nil {
return err
}
table := newTable(c.OutOrStdout(), r.Markdown)
table.SetHeader([]string{"NAME", "VALUE", "SET BY", "DESCRIPTION", "COUNT"})
for i := range r.List.Setters {
s := r.List.Setters[i]
v := s.Value
// if the setter is for a list, populate the values
if len(s.ListValues) > 0 {
v = strings.Join(s.ListValues, ",")
v = fmt.Sprintf("[%s]", v)
}
table.Append([]string{
s.Name, v, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count)})
}
table.Render()
if len(r.List.Setters) == 0 {
// exit non-0 if no matching setters are found
if ExitOnError {
os.Exit(1)
}
}
return nil
}
func (r *ListSettersRunner) ListSubstitutions(c *cobra.Command, args []string) error {
// use setters v2
path, err := ext.GetOpenAPIFile(args)
if err != nil {
return err
}
if err := r.List.ListSubst(path); err != nil {
return err
}
table := newTable(c.OutOrStdout(), r.Markdown)
table.SetHeader([]string{"SUBSTITUTION", "PATTERN", "SETTERS"})
for i := range r.List.Substitutions {
s := r.List.Substitutions[i]
setters := ""
for _, value := range s.Values {
setter := strings.TrimPrefix(value.Ref, setters2.DefinitionsPrefix+setters2.SetterDefinitionPrefix)
setters = setters + "," + setter
}
setters = fmt.Sprintf("[%s]", strings.TrimPrefix(setters, ","))
table.Append([]string{
s.Name, s.Pattern, setters})
}
if len(r.List.Substitutions) == 0 {
// exit non-0 if no matching substitutions are found
if ExitOnError {
os.Exit(1)
}
} else {
table.Render()
}
return nil
}
func newTable(o io.Writer, m bool) *tablewriter.Table {
table := tablewriter.NewWriter(o)
table.SetRowLine(false)

View File

@@ -104,6 +104,8 @@ spec:
image nginx me2 hello world 2 2
replicas 3 me1 hello world 1 1
tag 1.7.9 me3 hello world 3 1
SUBSTITUTION PATTERN SETTERS
image IMAGE:TAG [image,tag]
`,
},
{
@@ -176,6 +178,8 @@ spec:
image nginx me2 hello world 2 3
replicas 3 me1 hello world 1 2
tag 1.7.9 me3 hello world 3 2
SUBSTITUTION PATTERN SETTERS
image IMAGE:TAG [image,tag]
`,
},
{
@@ -247,6 +251,8 @@ spec:
`,
expected: ` NAME VALUE SET BY DESCRIPTION COUNT
image nginx me2 hello world 2 3
SUBSTITUTION PATTERN SETTERS
image IMAGE:TAG [image,tag]
`,
},
}

View File

@@ -0,0 +1,661 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package e2e
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestRunE2e(t *testing.T) {
binDir, err := ioutil.TempDir("", "kustomize-test-")
if !assert.NoError(t, err) {
t.FailNow()
}
//defer os.RemoveAll(binDir)
build(t, binDir)
tests := []struct {
name string
args func(string) []string
files func(string) map[string]string
expectedFiles func(string) map[string]string
expectedErr string
skipIfFalseEnv string
}{
{
name: "exec_function_no_args",
args: func(d string) []string {
return []string{
"--enable-exec", "--exec-path", filepath.Join(d, "e2econtainerconfig"),
}
},
files: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
a-string-value: ''
a-int-value: '0'
a-bool-value: 'false'
`,
}
},
},
{
name: "exec_function_args",
args: func(d string) []string {
return []string{
"--enable-exec", "--exec-path", filepath.Join(d, "e2econtainerconfig"),
"--", "stringValue=a", "intValue=1", "boolValue=true",
}
},
files: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
a-string-value: 'a'
a-int-value: '1'
a-bool-value: 'true'
`,
}
},
},
{
name: "exec_function_config",
args: func(d string) []string {
return []string{"--enable-exec"}
},
files: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": fmt.Sprintf(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
exec:
path: "%s"
`, filepath.Join(d, "e2econtainerconfig")),
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": fmt.Sprintf(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
exec:
path: "%s"
a-string-value: ''
a-int-value: '0'
a-bool-value: 'false'
`, filepath.Join(d, "e2econtainerconfig"))}
},
},
//
// Starklark function tests
//
{
name: "exec_function_config",
args: func(d string) []string {
return []string{"--enable-exec"}
},
files: func(d string) map[string]string {
return map[string]string{
"config.yaml": fmt.Sprintf(`
apiVersion: example.com/v1alpha1
kind: Input
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
exec:
path: "%s"
data:
stringValue: a
intValue: 2
boolValue: true
`, filepath.Join(d, "e2econtainerconfig")),
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"config.yaml": fmt.Sprintf(`
apiVersion: example.com/v1alpha1
kind: Input
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
exec:
path: "%s"
a-string-value: 'a'
a-int-value: '2'
a-bool-value: 'true'
data:
stringValue: a
intValue: 2
boolValue: true
`, filepath.Join(d, "e2econtainerconfig")),
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
a-string-value: 'a'
a-int-value: '2'
a-bool-value: 'true'
`,
}
},
},
{
//
// NOTE: Do not change the expected value of this test. It is to ensure that
// exec functions are off by default when run from the CLI.
// exec functions execute arbitrary code outside of a sandbox environment.
//
name: "exec_function_config_disabled",
args: func(d string) []string { return []string{} },
files: func(d string) map[string]string {
return map[string]string{
"config.yaml": fmt.Sprintf(`
apiVersion: example.com/v1alpha1
kind: Input
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
exec:
path: "%s"
data:
stringValue: a
intValue: 2
boolValue: true
`, filepath.Join(d, "e2econtainerconfig")),
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"config.yaml": fmt.Sprintf(`
apiVersion: example.com/v1alpha1
kind: Input
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
exec:
path: "%s"
data:
stringValue: a
intValue: 2
boolValue: true
`, filepath.Join(d, "e2econtainerconfig")),
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
},
{
name: "exec_function_no_enable",
expectedErr: "must specify --enable-exec with --exec-path",
args: func(d string) []string {
return []string{"--exec-path", filepath.Join(d, "e2econtainerconfig")}
},
files: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
a-string-value: ''
a-int-value: '0'
a-bool-value: 'false'
`,
}
},
},
//
// Container
//
{
name: "container_function_no_args",
skipIfFalseEnv: "KUSTOMIZE_DOCKER_E2E",
args: func(d string) []string {
return []string{"--image", "gcr.io/kustomize-functions/e2econtainerconfig"}
},
files: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
a-string-value: ''
a-int-value: '0'
a-bool-value: 'false'
`,
}
},
},
{
name: "container_function_args",
skipIfFalseEnv: "KUSTOMIZE_DOCKER_E2E",
args: func(d string) []string {
return []string{
"--image", "gcr.io/kustomize-functions/e2econtainerconfig",
"--", "stringValue=a", "intValue=1", "boolValue=true",
}
},
files: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
a-string-value: 'a'
a-int-value: '1'
a-bool-value: 'true'
`,
}
},
},
{
name: "container_function_config",
skipIfFalseEnv: "KUSTOMIZE_DOCKER_E2E",
args: func(d string) []string { return []string{} },
files: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
container:
image: "gcr.io/kustomize-functions/e2econtainerconfig"
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
container:
image: "gcr.io/kustomize-functions/e2econtainerconfig"
a-string-value: ''
a-int-value: '0'
a-bool-value: 'false'
`}
},
},
{
name: "container_function_config",
skipIfFalseEnv: "KUSTOMIZE_DOCKER_E2E",
args: func(d string) []string { return []string{} },
files: func(d string) map[string]string {
return map[string]string{
"config.yaml": `
apiVersion: example.com/v1alpha1
kind: Input
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
container:
image: "gcr.io/kustomize-functions/e2econtainerconfig"
data:
stringValue: a
intValue: 2
boolValue: true
`,
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"config.yaml": `
apiVersion: example.com/v1alpha1
kind: Input
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
container:
image: "gcr.io/kustomize-functions/e2econtainerconfig"
a-string-value: 'a'
a-int-value: '2'
a-bool-value: 'true'
data:
stringValue: a
intValue: 2
boolValue: true
`,
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
a-string-value: 'a'
a-int-value: '2'
a-bool-value: 'true'
`,
}
},
},
{
name: "starlark_function_config",
args: func(d string) []string { return []string{"--enable-star"} },
files: func(d string) map[string]string {
return map[string]string{
"script.star": `
# set the foo annotation on each resource
def run(r, fc):
for resource in r:
resource["metadata"]["annotations"]["a-string-value"] = fc["data"]["stringValue"]
resource["metadata"]["annotations"]["a-int-value"] = fc["data"]["intValue"]
resource["metadata"]["annotations"]["a-bool-value"] = fc["data"]["boolValue"]
run(ctx.resource_list["items"], ctx.resource_list["functionConfig"])
`,
"config.yaml": `
apiVersion: example.com/v1alpha1
kind: Input
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
starlark:
path: script.star
name: fn
data:
boolValue: true
intValue: 2
stringValue: a
`,
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"config.yaml": `
apiVersion: example.com/v1alpha1
kind: Input
metadata:
name: foo
annotations:
a-bool-value: true
a-int-value: 2
a-string-value: a
config.kubernetes.io/function: |
starlark:
path: script.star
name: fn
data:
boolValue: true
intValue: 2
stringValue: a
`,
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
a-bool-value: true
a-int-value: 2
a-string-value: a
`,
}
},
},
{
name: "starlark_function_path",
args: func(d string) []string {
return []string{
"--enable-star", "--star-path", "script.star",
"--", "stringValue=a", "intValue=2", "boolValue=true",
}
},
files: func(d string) map[string]string {
return map[string]string{
"script.star": `
# set the foo annotation on each resource
def run(r, fc):
for resource in r:
resource["metadata"]["annotations"]["a-string-value"] = fc["data"]["stringValue"]
resource["metadata"]["annotations"]["a-int-value"] = fc["data"]["intValue"]
resource["metadata"]["annotations"]["a-bool-value"] = fc["data"]["boolValue"]
run(ctx.resource_list["items"], ctx.resource_list["functionConfig"])
`,
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
`,
}
},
expectedFiles: func(d string) map[string]string {
return map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
annotations:
a-bool-value: true
a-int-value: 2
a-string-value: a
`,
}
},
},
}
for i := range tests {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
if tt.skipIfFalseEnv != "" && os.Getenv(tt.skipIfFalseEnv) == "false" {
t.Skip()
}
dir, err := ioutil.TempDir("", "kustomize-test-data-")
if !assert.NoError(t, err) {
t.FailNow()
}
defer os.RemoveAll(dir)
os.Chdir(dir)
// write the input
for path, data := range tt.files(binDir) {
err := ioutil.WriteFile(path, []byte(data), 0600)
if !assert.NoError(t, err) {
t.FailNow()
}
}
args := append([]string{"run", "."}, tt.args(binDir)...)
cmd := exec.Command(filepath.Join(binDir, "kyaml"), args...)
cmd.Dir = dir
var stdErr, stdOut bytes.Buffer
cmd.Stdout = &stdOut
cmd.Stderr = &stdErr
cmd.Env = os.Environ()
err = cmd.Run()
if tt.expectedErr != "" {
if !assert.Contains(t, stdErr.String(), tt.expectedErr) {
t.FailNow()
}
return
}
if !assert.NoError(t, err, stdErr.String()) {
t.FailNow()
}
for path, data := range tt.expectedFiles(binDir) {
b, err := ioutil.ReadFile(path)
if !assert.NoError(t, err) {
t.FailNow()
}
if !assert.Equal(t, strings.TrimSpace(data), strings.TrimSpace(string(b))) {
t.FailNow()
}
}
})
}
}
func build(t *testing.T, binDir string) {
build := exec.Command("go", "build", "-o",
filepath.Join(binDir, "e2econtainerconfig"))
build.Dir = "e2econtainerconfig"
build.Stdout = os.Stdout
build.Stderr = os.Stderr
if !assert.NoError(t, build.Run()) {
t.FailNow()
}
build = exec.Command("go", "build", "-o", filepath.Join(binDir, "kyaml"))
build.Dir = filepath.Join("..", "..", "..")
build.Stdout = os.Stdout
build.Stderr = os.Stderr
if !assert.NoError(t, build.Run()) {
t.FailNow()
}
if os.Getenv("KUSTOMIZE_DOCKER_E2E") == "false" {
return
}
build = exec.Command(
"docker", "build", ".", "-t", "gcr.io/kustomize-functions/e2econtainerconfig")
build.Dir = "e2econtainerconfig"
build.Stdout = os.Stdout
build.Stderr = os.Stderr
if !assert.NoError(t, build.Run()) {
t.FailNow()
}
}

View File

@@ -0,0 +1,12 @@
# Copyright 2019 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
FROM golang:1.13-stretch
ENV CGO_ENABLED=0
WORKDIR /go/src/
COPY . .
RUN go build -v -o /usr/local/bin/function ./
FROM alpine:latest
COPY --from=0 /usr/local/bin/function /usr/local/bin/function
CMD ["function"]

View File

@@ -0,0 +1,13 @@
# Copyright 2019 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
.PHONY: generate license fix vet fmt test build tidy
GOBIN := $(shell go env GOPATH)/bin
test:
go test
image:
docker build . -t gcr.io/kustomize-functions/e2econtainerconfig
docker push gcr.io/kustomize-functions/e2econtainerconfig

View File

@@ -0,0 +1,12 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package main contains a function to be used for e2e testing.
//
// The function is written using the framework, and parses the ResourceList.functionConfig
// into a go struct.
//
// The function will set 3 annotations on each resource.
//
// See https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md
package main

View File

@@ -0,0 +1,5 @@
module sigs.k8s.io/kustomize/cmd/config/internal/commands/e2e/e2econtainerconfig
go 1.14
require sigs.k8s.io/kustomize/kyaml v0.1.10

View File

@@ -0,0 +1,189 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
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-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/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/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
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-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
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.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
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/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-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/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
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/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/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/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.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
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/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
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/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-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/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/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/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-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/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/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
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.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/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-20181114220301-adae6a3d119a/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-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
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/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/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/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/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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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/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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/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.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=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/kustomize/kyaml v0.1.10 h1:ZZfBnA/kYa9ZxUFIgI9oq3pWKzzA1gGOKgU0Hv/NhVg=
sigs.k8s.io/kustomize/kyaml v0.1.10/go.mod h1:mPmeBSRy0LTMv6fSrYSoi2yIFNZVouGKDsTekE5kdhs=

View File

@@ -0,0 +1,60 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"fmt"
"os"
"sigs.k8s.io/kustomize/kyaml/fn/framework"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// Data contains the items
type Data struct {
StringValue string `yaml:"stringValue,omitempty"`
IntValue int `yaml:"intValue,omitempty"`
BoolValue bool `yaml:"boolValue,omitempty"`
}
// Example defines the ResourceList.functionConfig schema.
type Example struct {
// Data contains configuration data for the Example
// Nest values under Data so that the function can accept a ConfigMap as its
// functionConfig (`run` generates a ConfigMap for the functionConfig when run with --)
// e.g. `config run DIR/ --image my-image -- a-string-value=foo` will create the input
// with ResourceList.functionConfig.data.a-string-value=foo
Data Data `yaml:"data,omitempty"`
}
func main() {
functionConfig := &Example{}
resourceList := &framework.ResourceList{FunctionConfig: functionConfig}
cmd := framework.Command(resourceList, func() error {
for i := range resourceList.Items {
if err := resourceList.Items[i].PipeE(yaml.SetAnnotation("a-string-value",
functionConfig.Data.StringValue)); err != nil {
return err
}
if err := resourceList.Items[i].PipeE(yaml.SetAnnotation("a-int-value",
fmt.Sprintf("%v", functionConfig.Data.IntValue))); err != nil {
return err
}
if err := resourceList.Items[i].PipeE(yaml.SetAnnotation("a-bool-value",
fmt.Sprintf("%v", functionConfig.Data.BoolValue))); err != nil {
return err
}
}
return nil
})
if err := cmd.Execute(); err != nil {
os.Exit(1)
}
}

View File

@@ -11,7 +11,7 @@ import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio/filters"
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
"sigs.k8s.io/kustomize/kyaml/runfn"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
@@ -41,15 +41,20 @@ func GetRunFnRunner(name string) *RunFnRunner {
r.Command.Flags().StringVar(
&r.Image, "image", "",
"run this image as a function instead of discovering them.")
// NOTE: exec plugins execute arbitrary code -- never change the default value of this flag!!!
r.Command.Flags().BoolVar(
&r.EnableStar, "enable-star", false, "enable support for starlark functions.")
r.Command.Flags().MarkHidden("enable-star")
&r.EnableExec, "enable-exec", false /*do not change!*/, "enable support for exec functions -- note: exec functions run arbitrary code -- do not use for untrusted configs!!! (Alpha)")
r.Command.Flags().StringVar(
&r.StarPath, "star-path", "", "run a starlark script as a function.")
r.Command.Flags().MarkHidden("star-path")
&r.ExecPath, "exec-path", "", "run an executable as a function. (Alpha)")
r.Command.Flags().BoolVar(
&r.EnableStar, "enable-star", false, "enable support for starlark functions. (Alpha)")
r.Command.Flags().StringVar(
&r.StarName, "star-name", "", "name of starlark program.")
r.Command.Flags().MarkHidden("star-name")
&r.StarPath, "star-path", "", "run a starlark script as a function. (Alpha)")
r.Command.Flags().StringVar(
&r.StarName, "star-name", "", "name of starlark program. (Alpha)")
r.Command.Flags().StringVar(
&r.ResultsDir, "results-dir", "", "write function results to this dir")
r.Command.Flags().BoolVar(
&r.Network, "network", false, "enable network access for functions that declare it")
@@ -76,7 +81,10 @@ type RunFnRunner struct {
EnableStar bool
StarPath string
StarName string
EnableExec bool
ExecPath string
RunFns runfn.RunFns
ResultsDir string
Network bool
NetworkName string
Mounts []string
@@ -90,14 +98,13 @@ func (r *RunFnRunner) runE(c *cobra.Command, args []string) error {
// Functions to run.
func (r *RunFnRunner) getContainerFunctions(c *cobra.Command, args, dataItems []string) (
[]*yaml.RNode, error) {
if r.Image == "" && r.StarPath == "" {
if r.Image == "" && r.StarPath == "" && r.ExecPath == "" {
return nil, nil
}
var fn *yaml.RNode
var err error
// if image isn't specified, then Functions is empty
if r.Image != "" {
// create the function spec to set as an annotation
fn, err = yaml.Parse(`container: {}`)
@@ -139,8 +146,19 @@ func (r *RunFnRunner) getContainerFunctions(c *cobra.Command, args, dataItems []
if err != nil {
return nil, err
}
} else {
return nil, nil
} else if r.EnableExec && r.ExecPath != "" {
// create the function spec to set as an annotation
fn, err = yaml.Parse(`exec: {}`)
if err != nil {
return nil, err
}
err = fn.PipeE(
yaml.Lookup("exec"),
yaml.SetField("path", yaml.NewScalarRNode(r.ExecPath)))
if err != nil {
return nil, err
}
}
// create the function config
@@ -204,21 +222,25 @@ data: {}
return []*yaml.RNode{rc}, nil
}
func toStorageMounts(mounts []string) []filters.StorageMount {
var sms []filters.StorageMount
func toStorageMounts(mounts []string) []runtimeutil.StorageMount {
var sms []runtimeutil.StorageMount
for _, mount := range mounts {
sms = append(sms, filters.StringToStorageMount(mount))
sms = append(sms, runtimeutil.StringToStorageMount(mount))
}
return sms
}
func (r *RunFnRunner) preRunE(c *cobra.Command, args []string) error {
if r.EnableStar != (r.StarPath != "") {
return errors.Errorf("must specify --star-path with --enable-star")
if !r.EnableStar && r.StarPath != "" {
return errors.Errorf("must specify --enable-star with --star-path")
}
if !r.EnableExec && r.ExecPath != "" {
return errors.Errorf("must specify --enable-exec with --exec-path")
}
if c.ArgsLenAtDash() >= 0 && r.Image == "" &&
!(r.EnableStar && r.StarPath != "") {
!(r.EnableStar && r.StarPath != "") && !(r.EnableExec && r.ExecPath != "") {
return errors.Errorf("must specify --image")
}
@@ -266,7 +288,9 @@ func (r *RunFnRunner) preRunE(c *cobra.Command, args []string) error {
Network: r.Network,
NetworkName: r.NetworkName,
EnableStarlark: r.EnableStar,
EnableExec: r.EnableExec,
StorageMounts: storageMounts,
ResultsDir: r.ResultsDir,
}
// don't consider args for the function

View File

@@ -11,23 +11,25 @@ import (
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/kyaml/runfn"
)
// TestRunFnCommand_preRunE verifies that preRunE correctly parses the commandline
// flags and arguments into the RunFns structure to be executed.
func TestRunFnCommand_preRunE(t *testing.T) {
tests := []struct {
name string
args []string
expected string
err string
path string
input io.Reader
output io.Writer
functionPaths []string
network bool
networkName string
mount []string
name string
args []string
expected string
expectedStruct *runfn.RunFns
err string
path string
input io.Reader
output io.Writer
functionPaths []string
network bool
networkName string
mount []string
}{
{
name: "config map",
@@ -181,7 +183,7 @@ apiVersion: v1
"--star-name", "foo",
"--", "Foo", "g=h"},
path: "dir",
err: "must specify --star-path with --enable-star",
err: "must specify --enable-star with --star-path",
},
{
name: "image-star-not-enabled",
@@ -191,7 +193,17 @@ apiVersion: v1
"--star-name", "foo",
"--", "Foo", "g=h"},
path: "dir",
err: "must specify --star-path with --enable-star",
err: "must specify --enable-star with --star-path",
},
{
name: "star-enabled",
args: []string{"run", "dir", "--enable-star"},
path: "dir",
expectedStruct: &runfn.RunFns{
Path: "dir",
NetworkName: "bridge",
EnableStarlark: true,
},
},
{
name: "function paths",
@@ -234,6 +246,26 @@ metadata:
data: {g: h, i: j=k}
kind: Foo
apiVersion: v1
`,
},
{
name: "results_dir",
args: []string{"run", "dir", "--results-dir", "foo/", "--image", "foo:bar", "--", "a=b", "c=d", "e=f"},
path: "dir",
expectedStruct: &runfn.RunFns{
Path: "dir",
NetworkName: "bridge",
ResultsDir: "foo/",
},
expected: `
metadata:
name: function-input
annotations:
config.kubernetes.io/function: |
container: {image: 'foo:bar'}
data: {a: b, c: d, e: f}
kind: ConfigMap
apiVersion: v1
`,
},
{
@@ -324,6 +356,10 @@ apiVersion: v1
t.FailNow()
}
if !assert.Equal(t, r.RunFns, r.RunFns) {
t.FailNow()
}
if !assert.Equal(t, toStorageMounts(tt.mount), r.RunFns.StorageMounts) {
t.FailNow()
}
@@ -339,6 +375,14 @@ apiVersion: v1
}
}
if tt.expectedStruct != nil {
r.RunFns.Functions = nil
tt.expectedStruct.FunctionPaths = tt.functionPaths
if !assert.Equal(t, *tt.expectedStruct, r.RunFns) {
t.FailNow()
}
}
})
}

Some files were not shown because too many files have changed in this diff Show More