mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-30 01:46:23 +00:00
Compare commits
313 Commits
api/v0.8.9
...
revert-415
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d0b7e2113 | ||
|
|
c3a67cfdca | ||
|
|
4315e982be | ||
|
|
634464353f | ||
|
|
9c36004493 | ||
|
|
1b1034442c | ||
|
|
a89863c84c | ||
|
|
f7340e0615 | ||
|
|
bf6b207cc9 | ||
|
|
f93b4877f7 | ||
|
|
cd17338759 | ||
|
|
c46867c3a7 | ||
|
|
3c321ef79c | ||
|
|
7938fdb596 | ||
|
|
a2111869e6 | ||
|
|
f8288e2f02 | ||
|
|
f2f90d1185 | ||
|
|
459e800ecf | ||
|
|
8f00d3fd53 | ||
|
|
cd94cb13c6 | ||
|
|
e100be620e | ||
|
|
1e1b9b484a | ||
|
|
3e7246690f | ||
|
|
360585dfaf | ||
|
|
f604619dd5 | ||
|
|
0fa056327a | ||
|
|
6db2bf69f3 | ||
|
|
20fb9578c0 | ||
|
|
4eb8232495 | ||
|
|
6c4e8019f8 | ||
|
|
28707bf5df | ||
|
|
023a580f00 | ||
|
|
a2eaae5555 | ||
|
|
75df1a5422 | ||
|
|
f0b4cc4581 | ||
|
|
7a41e479c9 | ||
|
|
3350c7213c | ||
|
|
7b5e43d343 | ||
|
|
06661ea310 | ||
|
|
38b2b33503 | ||
|
|
f735d6fb3a | ||
|
|
5cb5e07ac0 | ||
|
|
54778504ed | ||
|
|
1bfe0d08dc | ||
|
|
56da9a58fc | ||
|
|
54383bca25 | ||
|
|
88461b4fed | ||
|
|
aabbea3e78 | ||
|
|
adedca09f2 | ||
|
|
9a27a9f19f | ||
|
|
3ebdb3fcef | ||
|
|
97e7cb1512 | ||
|
|
262a2d9288 | ||
|
|
91b862b556 | ||
|
|
b8ffc725c7 | ||
|
|
76f1411922 | ||
|
|
d1003d6f8f | ||
|
|
91f74e8d16 | ||
|
|
94c5096a95 | ||
|
|
f35aeb6a8e | ||
|
|
d6ce846047 | ||
|
|
ec069e4f19 | ||
|
|
c5adafd9ce | ||
|
|
16dcc98cff | ||
|
|
59c410a70a | ||
|
|
9b586162d0 | ||
|
|
803885049b | ||
|
|
be4fe7540e | ||
|
|
927568eea2 | ||
|
|
436d5e717c | ||
|
|
d37fa66ebc | ||
|
|
e8a4bf6edc | ||
|
|
35d1c3f9b4 | ||
|
|
e17785af21 | ||
|
|
0537b59f27 | ||
|
|
339e33d2f3 | ||
|
|
f082ac02cf | ||
|
|
9538ae1258 | ||
|
|
34981b664f | ||
|
|
477d8930e0 | ||
|
|
b5091a566a | ||
|
|
9981c45554 | ||
|
|
0f736ec7fd | ||
|
|
7826ad1e06 | ||
|
|
f4e6816338 | ||
|
|
4a13725678 | ||
|
|
ab9b010856 | ||
|
|
29be7fabe4 | ||
|
|
74e867833a | ||
|
|
91dc6d2a0f | ||
|
|
3c1fd0e9cf | ||
|
|
4deeb7d59b | ||
|
|
89b12cfc62 | ||
|
|
c07ffa5c1e | ||
|
|
259fcfcef8 | ||
|
|
f81201b74d | ||
|
|
6dbc74b32e | ||
|
|
ed38b5fe2b | ||
|
|
a84badb834 | ||
|
|
e1804cbc76 | ||
|
|
d13eef7951 | ||
|
|
0b4c6baf44 | ||
|
|
b3af54340c | ||
|
|
8c14b9d1af | ||
|
|
d818ccae92 | ||
|
|
4cea8b9785 | ||
|
|
84a36801e0 | ||
|
|
6eb7b3508d | ||
|
|
2a5f4ac7d7 | ||
|
|
518a16d3ac | ||
|
|
d53a2ad45d | ||
|
|
bb02a7645b | ||
|
|
5a9d90c872 | ||
|
|
4fd7269643 | ||
|
|
1eb3c1a075 | ||
|
|
a1746f2f8c | ||
|
|
b727febd08 | ||
|
|
c819d69ae4 | ||
|
|
bb6f83fb96 | ||
|
|
02d14d724a | ||
|
|
aa92d83d8c | ||
|
|
5427ab7cc3 | ||
|
|
e583f199b8 | ||
|
|
b465c20f65 | ||
|
|
5c2c617ff0 | ||
|
|
3ab0665c19 | ||
|
|
4b66043735 | ||
|
|
979f03e76c | ||
|
|
c8b049f57f | ||
|
|
f3d8883046 | ||
|
|
e308f321d3 | ||
|
|
beea785ead | ||
|
|
95c5b686be | ||
|
|
0ddf68cc8a | ||
|
|
4cadad5cfe | ||
|
|
9e4a6397d6 | ||
|
|
2e8a3b7c45 | ||
|
|
276d0430bf | ||
|
|
1aa7a1e709 | ||
|
|
78737f5a38 | ||
|
|
dac84d867e | ||
|
|
217e5c7268 | ||
|
|
936ac37a2e | ||
|
|
cb4f5c3983 | ||
|
|
1801d33287 | ||
|
|
b01da61d83 | ||
|
|
23e28bb18a | ||
|
|
a1f1c2d32f | ||
|
|
10331d9560 | ||
|
|
60038d44f9 | ||
|
|
24d06f83ca | ||
|
|
e76638f98d | ||
|
|
ef1b9d4854 | ||
|
|
3c0f805674 | ||
|
|
324581594c | ||
|
|
7fae7d1bd6 | ||
|
|
0af3a75708 | ||
|
|
d39d7db9ed | ||
|
|
a04a6de0ef | ||
|
|
69a6708f9b | ||
|
|
c19a972739 | ||
|
|
2e674337b3 | ||
|
|
727e24f365 | ||
|
|
7e8ba62e9f | ||
|
|
fe60d0c403 | ||
|
|
2e0556b544 | ||
|
|
479acac581 | ||
|
|
3b37fed24b | ||
|
|
8fdb3f1703 | ||
|
|
95e242353b | ||
|
|
199802a176 | ||
|
|
065432e074 | ||
|
|
62fd36facb | ||
|
|
f121e74744 | ||
|
|
5aa2f534be | ||
|
|
86dd74fd62 | ||
|
|
218da9858f | ||
|
|
cebda58437 | ||
|
|
6a82437bc9 | ||
|
|
6b9e8eb891 | ||
|
|
615984bf2d | ||
|
|
bc6ac8a68a | ||
|
|
39f24ef8d2 | ||
|
|
24294d3bd0 | ||
|
|
234fcbfc02 | ||
|
|
b54093ebca | ||
|
|
db307a7084 | ||
|
|
a0c7997b66 | ||
|
|
7458a53a73 | ||
|
|
cf6e6ca4db | ||
|
|
e847ec7474 | ||
|
|
440026b9b3 | ||
|
|
64331ad845 | ||
|
|
294070b3ab | ||
|
|
cabbea0d97 | ||
|
|
732a8522df | ||
|
|
8f82c4c748 | ||
|
|
d0bc25f339 | ||
|
|
ed3200e4f5 | ||
|
|
a3ed120efb | ||
|
|
f1b191c02f | ||
|
|
1493b24b46 | ||
|
|
5993eae1aa | ||
|
|
3e506eae02 | ||
|
|
0305860078 | ||
|
|
0205090e0d | ||
|
|
6adefe4562 | ||
|
|
da1bd901b4 | ||
|
|
636b9c7aeb | ||
|
|
942f112ef5 | ||
|
|
03bbb076bf | ||
|
|
e468d6b4d2 | ||
|
|
57206a628d | ||
|
|
f061bb887b | ||
|
|
75fd9a43a3 | ||
|
|
58165dfc89 | ||
|
|
0e8257c387 | ||
|
|
62e78f8349 | ||
|
|
84724a3ebf | ||
|
|
23544e0431 | ||
|
|
b1fda3d62e | ||
|
|
b8ae69b748 | ||
|
|
4014440d06 | ||
|
|
74b0b3adc6 | ||
|
|
382f09a126 | ||
|
|
f9afdc5c95 | ||
|
|
5e4fb4796e | ||
|
|
76f8988865 | ||
|
|
fa3e829eb6 | ||
|
|
d9435bd1b1 | ||
|
|
af96bb4bda | ||
|
|
8607e0adec | ||
|
|
5a2a7709a4 | ||
|
|
437e8f90f6 | ||
|
|
06ac670951 | ||
|
|
3ee1579688 | ||
|
|
5954314b98 | ||
|
|
c0324456a7 | ||
|
|
172adc404f | ||
|
|
501748192b | ||
|
|
f6e6ac0320 | ||
|
|
a10ce1d787 | ||
|
|
839cc2467c | ||
|
|
dbc11ed29f | ||
|
|
0f614e92f7 | ||
|
|
afaf7c62bc | ||
|
|
78d22069d7 | ||
|
|
22720a8b7a | ||
|
|
38c66d213a | ||
|
|
871de80544 | ||
|
|
c24daec480 | ||
|
|
0849d12572 | ||
|
|
23bd8ff749 | ||
|
|
b5759305af | ||
|
|
da518668b5 | ||
|
|
51605beb3b | ||
|
|
2646861a4c | ||
|
|
f8c910bd3b | ||
|
|
cb82dced8a | ||
|
|
f618f9ce96 | ||
|
|
020dc9c216 | ||
|
|
a6b9445702 | ||
|
|
36408a120c | ||
|
|
c1bca9cd62 | ||
|
|
701973b73e | ||
|
|
24a64bdee3 | ||
|
|
3f3d3b17a4 | ||
|
|
53c87a32e9 | ||
|
|
0fdf0f825f | ||
|
|
73da51d0ac | ||
|
|
df10d5a17d | ||
|
|
9557888b32 | ||
|
|
3e14a31312 | ||
|
|
dca13a4770 | ||
|
|
017a094438 | ||
|
|
b8e7cf04b6 | ||
|
|
a8dacdaffc | ||
|
|
5c4e363f11 | ||
|
|
1e3ce57077 | ||
|
|
01ddeb476d | ||
|
|
714af0cd66 | ||
|
|
82abd7e9ea | ||
|
|
823ff2d048 | ||
|
|
fcfdf6be51 | ||
|
|
627118c438 | ||
|
|
5bb7364967 | ||
|
|
a46926c1eb | ||
|
|
4f760a0850 | ||
|
|
e905411207 | ||
|
|
1eb77a6cab | ||
|
|
8b1704bcf3 | ||
|
|
a0edb2d966 | ||
|
|
02dff45d7d | ||
|
|
3cf18adae9 | ||
|
|
2bec25b46e | ||
|
|
8ee308d5d6 | ||
|
|
3c3c97f9b5 | ||
|
|
c3e8f6008e | ||
|
|
660847225d | ||
|
|
48d16f877b | ||
|
|
a4f4945455 | ||
|
|
bd7229ea17 | ||
|
|
72441ce3ef | ||
|
|
fe5b7a3b41 | ||
|
|
a4db686b6c | ||
|
|
10026758d3 | ||
|
|
c8dddac5b9 | ||
|
|
5a8a4d47a5 | ||
|
|
6c35c06f3e | ||
|
|
1235047742 | ||
|
|
45fc67062e | ||
|
|
d03a5ab95f | ||
|
|
53f78260a9 |
15
.github/workflows/go.yml
vendored
15
.github/workflows/go.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: ./scripts/kyaml-pre-commit.sh
|
run: ./hack/kyaml-pre-commit.sh
|
||||||
env:
|
env:
|
||||||
KUSTOMIZE_DOCKER_E2E: false # don't need to do e2e tests for linting
|
KUSTOMIZE_DOCKER_E2E: false # don't need to do e2e tests for linting
|
||||||
|
|
||||||
@@ -45,6 +45,10 @@ jobs:
|
|||||||
run: go test -cover ./...
|
run: go test -cover ./...
|
||||||
working-directory: ./kyaml
|
working-directory: ./kyaml
|
||||||
|
|
||||||
|
- name: Test api
|
||||||
|
run: go test -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
|
||||||
|
working-directory: ./api
|
||||||
|
|
||||||
- name: Test cmd/config
|
- name: Test cmd/config
|
||||||
run: go test -cover ./...
|
run: go test -cover ./...
|
||||||
working-directory: ./cmd/config
|
working-directory: ./cmd/config
|
||||||
@@ -69,6 +73,10 @@ jobs:
|
|||||||
run: go test -cover ./...
|
run: go test -cover ./...
|
||||||
working-directory: ./kyaml
|
working-directory: ./kyaml
|
||||||
|
|
||||||
|
- name: Test api
|
||||||
|
run: go test -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
|
||||||
|
working-directory: ./api
|
||||||
|
|
||||||
- name: Test cmd/config
|
- name: Test cmd/config
|
||||||
run: go test -cover ./...
|
run: go test -cover ./...
|
||||||
working-directory: ./cmd/config
|
working-directory: ./cmd/config
|
||||||
@@ -93,6 +101,11 @@ jobs:
|
|||||||
run: go test -cover ./...
|
run: go test -cover ./...
|
||||||
working-directory: ./kyaml
|
working-directory: ./kyaml
|
||||||
|
|
||||||
|
# TODO: uncomment once Windows tests are passing.
|
||||||
|
# - name: Test api
|
||||||
|
# run: go test -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
|
||||||
|
# working-directory: ./api
|
||||||
|
|
||||||
- name: Test cmd/config
|
- name: Test cmd/config
|
||||||
run: go test -cover ./...
|
run: go test -cover ./...
|
||||||
working-directory: ./cmd/config
|
working-directory: ./cmd/config
|
||||||
|
|||||||
@@ -20,6 +20,20 @@ We have full documentation on how to get started contributing here:
|
|||||||
|
|
||||||
- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers!
|
- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers!
|
||||||
|
|
||||||
|
## Contributor Ladder
|
||||||
|
|
||||||
|
Kustomize generally follows the [Kubernetes Community Membership](https://github.com/kubernetes/community/blob/master/community-membership.md) contributor ladder. Roles are as follows:
|
||||||
|
|
||||||
|
1. Contributor: Anyone who actively contributes code, issues or reviews to the project. There are no Kustomize-specific requirements for this status. All contributors must [sign the CLA](https://github.com/kubernetes/community/tree/master/contributors/guide#prerequisites).
|
||||||
|
1. Member/Reviewer: All Kubernetes-SIGs org members have LGTM rights on the Kustomize repo. There are no Kustomize-specific requirements. Kustomize does not currently have any formal reviewers, but the role will be created if there is interest.
|
||||||
|
1. Maintainer/Approver: Highly experienced active reviewer and contributor to Kustomize. Has both LTGM and approval rights on the Kustomize repo, as well as [Github "maintain" rights](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization#repository-access-for-each-permission-level).
|
||||||
|
1. Admin/Owner: Maintainer who sets technical direction and makes or approves design decisions for the project. Has LGTM and approval rights on the Kustomize repo as well as [Github "admin" rights](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization#repository-access-for-each-permission-level).
|
||||||
|
|
||||||
|
Administrative notes:
|
||||||
|
- Maintainers and admins must be added to the appropriate list both [in the Kustomize repo](https://github.com/kubernetes-sigs/kustomize/blob/8049f7b1af52e8a7ec26faf6cf714f560d0043c5/OWNERS_ALIASES) and [in the community repo](https://github.com/kubernetes/org/blob/main/config/kubernetes-sigs/sig-cli/teams.yaml). If this isn't done, the individual in question will lack either PR approval rights (Kustomize list) or the appropriate Github repository permissions (community list).
|
||||||
|
- The spec for the OWNERS file is [in the community repo](https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md).
|
||||||
|
|
||||||
|
|
||||||
## Contact Information
|
## Contact Information
|
||||||
|
|
||||||
- [Slack channel](https://kubernetes.slack.com/messages/sig-cli)
|
- [Slack channel](https://kubernetes.slack.com/messages/sig-cli)
|
||||||
|
|||||||
75
Makefile
75
Makefile
@@ -4,12 +4,15 @@
|
|||||||
# Makefile for kustomize CLI and API.
|
# Makefile for kustomize CLI and API.
|
||||||
|
|
||||||
SHELL := /usr/bin/env bash
|
SHELL := /usr/bin/env bash
|
||||||
|
GOOS = $(shell go env GOOS)
|
||||||
|
GOARCH = $(shell go env GOARCH)
|
||||||
MYGOBIN = $(shell go env GOBIN)
|
MYGOBIN = $(shell go env GOBIN)
|
||||||
ifeq ($(MYGOBIN),)
|
ifeq ($(MYGOBIN),)
|
||||||
MYGOBIN = $(shell go env GOPATH)/bin
|
MYGOBIN = $(shell go env GOPATH)/bin
|
||||||
endif
|
endif
|
||||||
export PATH := $(MYGOBIN):$(PATH)
|
export PATH := $(MYGOBIN):$(PATH)
|
||||||
MODULES := '"cmd/config" "api/" "kustomize/" "kyaml/"'
|
MODULES := '"cmd/config" "api/" "kustomize/" "kyaml/"'
|
||||||
|
LATEST_V4_RELEASE=v4.3.0
|
||||||
|
|
||||||
# Provide defaults for REPO_OWNER and REPO_NAME if not present.
|
# Provide defaults for REPO_OWNER and REPO_NAME if not present.
|
||||||
# Typically these values would be provided by Prow.
|
# Typically these values would be provided by Prow.
|
||||||
@@ -22,58 +25,48 @@ REPO_NAME := "kustomize"
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: verify-kustomize
|
all: install-tools verify-kustomize
|
||||||
|
|
||||||
.PHONY: verify-kustomize
|
.PHONY: verify-kustomize
|
||||||
verify-kustomize: \
|
verify-kustomize: \
|
||||||
lint-kustomize \
|
lint-kustomize \
|
||||||
test-unit-kustomize-all \
|
test-unit-kustomize-all \
|
||||||
test-examples-kustomize-against-HEAD \
|
test-examples-kustomize-against-HEAD \
|
||||||
test-examples-kustomize-against-4.0
|
test-examples-kustomize-against-v4-release
|
||||||
|
|
||||||
# The following target referenced by a file in
|
# The following target referenced by a file in
|
||||||
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
|
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
|
||||||
.PHONY: prow-presubmit-check
|
.PHONY: prow-presubmit-check
|
||||||
prow-presubmit-check: \
|
prow-presubmit-check: \
|
||||||
|
install-tools \
|
||||||
lint-kustomize \
|
lint-kustomize \
|
||||||
test-multi-module \
|
test-multi-module \
|
||||||
test-unit-kustomize-all \
|
test-unit-kustomize-all \
|
||||||
test-unit-cmd-all \
|
test-unit-cmd-all \
|
||||||
test-go-mod \
|
test-go-mod \
|
||||||
test-examples-kustomize-against-HEAD \
|
test-examples-kustomize-against-HEAD \
|
||||||
test-examples-kustomize-against-4.0
|
test-examples-kustomize-against-v4-release
|
||||||
|
|
||||||
.PHONY: verify-kustomize-e2e
|
.PHONY: verify-kustomize-e2e
|
||||||
verify-kustomize-e2e: test-examples-e2e-kustomize
|
verify-kustomize-e2e: test-examples-e2e-kustomize
|
||||||
|
|
||||||
# Other builds in this repo might want a different linter version.
|
# Other builds in this repo might want a different linter version.
|
||||||
# Without one Makefile to rule them all, the different makes
|
# Without one Makefile to rule them all, the different makes
|
||||||
# cannot assume that golanci-lint is at the version they want
|
# cannot assume that golanci-lint is at the version they want.
|
||||||
# since everything uses the same implicit GOPATH.
|
# This installs what kustomize wants to use.
|
||||||
# This installs in a temp dir to avoid overwriting someone else's
|
|
||||||
# linter, then installs in MYGOBIN with a new name.
|
|
||||||
# Version pinned by hack/go.mod
|
|
||||||
$(MYGOBIN)/golangci-lint-kustomize:
|
$(MYGOBIN)/golangci-lint-kustomize:
|
||||||
( \
|
rm -f $(CURDIR)/hack/golangci-lint
|
||||||
set -e; \
|
GOBIN=$(CURDIR)/hack go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.23.8
|
||||||
cd hack; \
|
mv $(CURDIR)/hack/golangci-lint $(MYGOBIN)/golangci-lint-kustomize
|
||||||
GO111MODULE=on go build -tags=tools -o $(MYGOBIN)/golangci-lint-kustomize github.com/golangci/golangci-lint/cmd/golangci-lint; \
|
|
||||||
)
|
|
||||||
|
|
||||||
# Install from version specified in api/go.mod.
|
|
||||||
$(MYGOBIN)/mdrip:
|
$(MYGOBIN)/mdrip:
|
||||||
cd api; \
|
go install github.com/monopole/mdrip@v1.0.2
|
||||||
go install github.com/monopole/mdrip
|
|
||||||
|
|
||||||
# Install from version specified in api/go.mod.
|
|
||||||
$(MYGOBIN)/stringer:
|
$(MYGOBIN)/stringer:
|
||||||
cd api; \
|
go get golang.org/x/tools/cmd/stringer
|
||||||
go install golang.org/x/tools/cmd/stringer
|
|
||||||
|
|
||||||
# Install from version specified in api/go.mod.
|
|
||||||
$(MYGOBIN)/goimports:
|
$(MYGOBIN)/goimports:
|
||||||
cd api; \
|
go get golang.org/x/tools/cmd/goimports
|
||||||
go install golang.org/x/tools/cmd/goimports
|
|
||||||
|
|
||||||
# Build from local source.
|
# Build from local source.
|
||||||
$(MYGOBIN)/gorepomod:
|
$(MYGOBIN)/gorepomod:
|
||||||
@@ -141,6 +134,7 @@ pSrc=plugin/builtin
|
|||||||
_builtinplugins = \
|
_builtinplugins = \
|
||||||
AnnotationsTransformer.go \
|
AnnotationsTransformer.go \
|
||||||
ConfigMapGenerator.go \
|
ConfigMapGenerator.go \
|
||||||
|
IAMPolicyGenerator.go \
|
||||||
HashTransformer.go \
|
HashTransformer.go \
|
||||||
ImageTagTransformer.go \
|
ImageTagTransformer.go \
|
||||||
LabelTransformer.go \
|
LabelTransformer.go \
|
||||||
@@ -168,6 +162,7 @@ builtinplugins = $(patsubst %,$(pGen)/%,$(_builtinplugins))
|
|||||||
# that file, will be recreated.
|
# that file, will be recreated.
|
||||||
$(pGen)/AnnotationsTransformer.go: $(pSrc)/annotationstransformer/AnnotationsTransformer.go
|
$(pGen)/AnnotationsTransformer.go: $(pSrc)/annotationstransformer/AnnotationsTransformer.go
|
||||||
$(pGen)/ConfigMapGenerator.go: $(pSrc)/configmapgenerator/ConfigMapGenerator.go
|
$(pGen)/ConfigMapGenerator.go: $(pSrc)/configmapgenerator/ConfigMapGenerator.go
|
||||||
|
$(pGen)/GkeSaGenerator.go: $(pSrc)/gkesagenerator/GkeSaGenerator.go
|
||||||
$(pGen)/HashTransformer.go: $(pSrc)/hashtransformer/HashTransformer.go
|
$(pGen)/HashTransformer.go: $(pSrc)/hashtransformer/HashTransformer.go
|
||||||
$(pGen)/ImageTagTransformer.go: $(pSrc)/imagetagtransformer/ImageTagTransformer.go
|
$(pGen)/ImageTagTransformer.go: $(pSrc)/imagetagtransformer/ImageTagTransformer.go
|
||||||
$(pGen)/LabelTransformer.go: $(pSrc)/labeltransformer/LabelTransformer.go
|
$(pGen)/LabelTransformer.go: $(pSrc)/labeltransformer/LabelTransformer.go
|
||||||
@@ -211,7 +206,7 @@ clean-kustomize-external-go-plugin:
|
|||||||
### End kustomize plugin rules.
|
### End kustomize plugin rules.
|
||||||
|
|
||||||
.PHONY: lint-kustomize
|
.PHONY: lint-kustomize
|
||||||
lint-kustomize: install-tools $(builtinplugins)
|
lint-kustomize: $(MYGOBIN)/golangci-lint-kustomize $(builtinplugins)
|
||||||
cd api; $(MYGOBIN)/golangci-lint-kustomize \
|
cd api; $(MYGOBIN)/golangci-lint-kustomize \
|
||||||
-c ../.golangci-kustomize.yml \
|
-c ../.golangci-kustomize.yml \
|
||||||
run ./...
|
run ./...
|
||||||
@@ -251,10 +246,10 @@ test-unit-kustomize-all: \
|
|||||||
test-unit-kustomize-plugins
|
test-unit-kustomize-plugins
|
||||||
|
|
||||||
test-unit-cmd-all:
|
test-unit-cmd-all:
|
||||||
./scripts/kyaml-pre-commit.sh
|
./hack/kyaml-pre-commit.sh
|
||||||
|
|
||||||
test-go-mod:
|
test-go-mod:
|
||||||
./scripts/check-go-mod.sh
|
./hack/check-go-mod.sh
|
||||||
|
|
||||||
# Environment variables are defined at
|
# Environment variables are defined at
|
||||||
# https://github.com/kubernetes/test-infra/blob/master/prow/jobs.md#job-environment-variables
|
# https://github.com/kubernetes/test-infra/blob/master/prow/jobs.md#job-environment-variables
|
||||||
@@ -266,7 +261,7 @@ test-multi-module: $(MYGOBIN)/prchecker
|
|||||||
export REPO_NAME=$(REPO_NAME); \
|
export REPO_NAME=$(REPO_NAME); \
|
||||||
export PULL_NUMBER=$(PULL_NUMBER); \
|
export PULL_NUMBER=$(PULL_NUMBER); \
|
||||||
export MODULES=$(MODULES); \
|
export MODULES=$(MODULES); \
|
||||||
./scripts/check-multi-module.sh; \
|
./hack/check-multi-module.sh; \
|
||||||
)
|
)
|
||||||
|
|
||||||
.PHONY:
|
.PHONY:
|
||||||
@@ -284,8 +279,8 @@ test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
|
|||||||
./hack/testExamplesAgainstKustomize.sh HEAD
|
./hack/testExamplesAgainstKustomize.sh HEAD
|
||||||
|
|
||||||
.PHONY:
|
.PHONY:
|
||||||
test-examples-kustomize-against-4.0: $(MYGOBIN)/mdrip
|
test-examples-kustomize-against-v4-release: $(MYGOBIN)/mdrip
|
||||||
./hack/testExamplesAgainstKustomize.sh v4@v4.0.5
|
./hack/testExamplesAgainstKustomize.sh v4@$(LATEST_V4_RELEASE)
|
||||||
|
|
||||||
# linux only.
|
# linux only.
|
||||||
# This is for testing an example plugin that
|
# This is for testing an example plugin that
|
||||||
@@ -297,8 +292,8 @@ $(MYGOBIN)/kubeval:
|
|||||||
( \
|
( \
|
||||||
set -e; \
|
set -e; \
|
||||||
d=$(shell mktemp -d); cd $$d; \
|
d=$(shell mktemp -d); cd $$d; \
|
||||||
wget https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz; \
|
wget https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-$(GOOS)-$(GOARCH).tar.gz; \
|
||||||
tar xf kubeval-linux-amd64.tar.gz; \
|
tar xf kubeval-$(GOOS)-$(GOARCH).tar.gz; \
|
||||||
mv kubeval $(MYGOBIN); \
|
mv kubeval $(MYGOBIN); \
|
||||||
rm -rf $$d; \
|
rm -rf $$d; \
|
||||||
)
|
)
|
||||||
@@ -312,10 +307,10 @@ $(MYGOBIN)/helmV2:
|
|||||||
( \
|
( \
|
||||||
set -e; \
|
set -e; \
|
||||||
d=$(shell mktemp -d); cd $$d; \
|
d=$(shell mktemp -d); cd $$d; \
|
||||||
tgzFile=helm-v2.13.1-linux-amd64.tar.gz; \
|
tgzFile=helm-v2.13.1-$(GOOS)-$(GOARCH).tar.gz; \
|
||||||
wget https://storage.googleapis.com/kubernetes-helm/$$tgzFile; \
|
wget https://storage.googleapis.com/kubernetes-helm/$$tgzFile; \
|
||||||
tar -xvzf $$tgzFile; \
|
tar -xvzf $$tgzFile; \
|
||||||
mv linux-amd64/helm $(MYGOBIN)/helmV2; \
|
mv $(GOOS)-$(GOARCH)/helm $(MYGOBIN)/helmV2; \
|
||||||
rm -rf $$d \
|
rm -rf $$d \
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -325,10 +320,10 @@ $(MYGOBIN)/helmV3:
|
|||||||
( \
|
( \
|
||||||
set -e; \
|
set -e; \
|
||||||
d=$(shell mktemp -d); cd $$d; \
|
d=$(shell mktemp -d); cd $$d; \
|
||||||
tgzFile=helm-v3.5.3-linux-amd64.tar.gz; \
|
tgzFile=helm-v3.5.3-$(GOOS)-$(GOARCH).tar.gz; \
|
||||||
wget https://get.helm.sh/$$tgzFile; \
|
wget https://get.helm.sh/$$tgzFile; \
|
||||||
tar -xvzf $$tgzFile; \
|
tar -xvzf $$tgzFile; \
|
||||||
mv linux-amd64/helm $(MYGOBIN)/helmV3; \
|
mv $(GOOS)-$(GOARCH)/helm $(MYGOBIN)/helmV3; \
|
||||||
rm -rf $$d \
|
rm -rf $$d \
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -336,7 +331,7 @@ $(MYGOBIN)/kind:
|
|||||||
( \
|
( \
|
||||||
set -e; \
|
set -e; \
|
||||||
d=$(shell mktemp -d); cd $$d; \
|
d=$(shell mktemp -d); cd $$d; \
|
||||||
wget -O ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-$(shell uname)-amd64; \
|
wget -O ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-$(GOOS)-$(GOARCH); \
|
||||||
chmod +x ./kind; \
|
chmod +x ./kind; \
|
||||||
mv ./kind $(MYGOBIN); \
|
mv ./kind $(MYGOBIN); \
|
||||||
rm -rf $$d; \
|
rm -rf $$d; \
|
||||||
@@ -347,10 +342,10 @@ $(MYGOBIN)/gh:
|
|||||||
( \
|
( \
|
||||||
set -e; \
|
set -e; \
|
||||||
d=$(shell mktemp -d); cd $$d; \
|
d=$(shell mktemp -d); cd $$d; \
|
||||||
tgzFile=gh_1.0.0_linux_amd64.tar.gz; \
|
tgzFile=gh_1.0.0_$(GOOS)_$(GOARCH).tar.gz; \
|
||||||
wget https://github.com/cli/cli/releases/download/v1.0.0/$$tgzFile; \
|
wget https://github.com/cli/cli/releases/download/v1.0.0/$$tgzFile; \
|
||||||
tar -xvzf $$tgzFile; \
|
tar -xvzf $$tgzFile; \
|
||||||
mv gh_1.0.0_linux_amd64/bin/gh $(MYGOBIN)/gh; \
|
mv gh_1.0.0_$(GOOS)_$(GOARCH)/bin/gh $(MYGOBIN)/gh; \
|
||||||
rm -rf $$d \
|
rm -rf $$d \
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -358,8 +353,12 @@ $(MYGOBIN)/gh:
|
|||||||
clean: clean-kustomize-external-go-plugin
|
clean: clean-kustomize-external-go-plugin
|
||||||
go clean --cache
|
go clean --cache
|
||||||
rm -f $(builtinplugins)
|
rm -f $(builtinplugins)
|
||||||
rm -f $(MYGOBIN)/kustomize
|
rm -f $(MYGOBIN)/goimports
|
||||||
rm -f $(MYGOBIN)/golangci-lint-kustomize
|
rm -f $(MYGOBIN)/golangci-lint-kustomize
|
||||||
|
rm -f $(MYGOBIN)/kustomize
|
||||||
|
rm -f $(MYGOBIN)/mdrip
|
||||||
|
rm -f $(MYGOBIN)/prchecker
|
||||||
|
rm -f $(MYGOBIN)/stringer
|
||||||
|
|
||||||
# Handle pluginator manually.
|
# Handle pluginator manually.
|
||||||
# rm -f $(MYGOBIN)/pluginator
|
# rm -f $(MYGOBIN)/pluginator
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
|
# Keep *-admins and *-maintainers list in sync with corresponding lists in
|
||||||
|
# https://github.com/kubernetes/org/blob/main/config/kubernetes-sigs/sig-cli/teams.yaml
|
||||||
aliases:
|
aliases:
|
||||||
kustomize-admins:
|
kustomize-admins:
|
||||||
|
- knverey
|
||||||
- monopole
|
- monopole
|
||||||
- pwittrock
|
- pwittrock
|
||||||
kustomize-maintainers:
|
kustomize-maintainers:
|
||||||
- droot
|
|
||||||
- justinsb
|
- justinsb
|
||||||
- knverey
|
|
||||||
- monopole
|
|
||||||
- mortent
|
- mortent
|
||||||
- natasha41575
|
- natasha41575
|
||||||
- phanimarupaka
|
- phanimarupaka
|
||||||
- pwittrock
|
|
||||||
- Shell32-Natsu
|
- Shell32-Natsu
|
||||||
# emeritus
|
emeritus-maintainers:
|
||||||
# - liujingfang1
|
- liujingfang1
|
||||||
# - mengqiy
|
- mengqiy
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -22,15 +22,22 @@ This tool is sponsored by [sig-cli] ([KEP]).
|
|||||||
|
|
||||||
The kustomize build flow at [v2.0.3] was added
|
The kustomize build flow at [v2.0.3] was added
|
||||||
to [kubectl v1.14][kubectl announcement]. The kustomize
|
to [kubectl v1.14][kubectl announcement]. The kustomize
|
||||||
flow in kubectl has remained frozen at v2.0.3 while work
|
flow in kubectl remained frozen at v2.0.3 until kubectl v1.21,
|
||||||
to extract kubectl from the k/k repo, and work to remove
|
which [updated it to v4.0.5][kust-in-kubectl update]. It will
|
||||||
kustomize's dependence on core k/k code ([#2506]) has proceeded.
|
be updated on a regular basis going forward, and such updates
|
||||||
The reintegration effort is tracked in [#1500] (and its blocking
|
will be reflected in the Kubernetes release notes.
|
||||||
issues).
|
|
||||||
|
| Kubectl version | Kustomize version |
|
||||||
|
| --- | --- |
|
||||||
|
| < v1.14 | n/a |
|
||||||
|
| v1.14-v1.20 | v2.0.3 |
|
||||||
|
| v1.21 | v4.0.5 |
|
||||||
|
| v1.22 | v4.2.0 |
|
||||||
|
|
||||||
[v2.0.3]: /../../tree/v2.0.3
|
[v2.0.3]: /../../tree/v2.0.3
|
||||||
[#2506]: https://github.com/kubernetes-sigs/kustomize/issues/2506
|
[#2506]: https://github.com/kubernetes-sigs/kustomize/issues/2506
|
||||||
[#1500]: https://github.com/kubernetes-sigs/kustomize/issues/1500
|
[#1500]: https://github.com/kubernetes-sigs/kustomize/issues/1500
|
||||||
|
[kust-in-kubectl update]: https://github.com/kubernetes/kubernetes/blob/4d75a6238a6e330337526e0513e67d02b1940b63/CHANGELOG/CHANGELOG-1.21.md#kustomize-updates-in-kubectl
|
||||||
|
|
||||||
For examples and guides for using the kubectl integration please
|
For examples and guides for using the kubectl integration please
|
||||||
see the [kubectl book] or the [kubernetes documentation].
|
see the [kubectl book] or the [kubernetes documentation].
|
||||||
@@ -145,7 +152,7 @@ is governed by the [Kubernetes Code of Conduct].
|
|||||||
[`make`]: https://www.gnu.org/software/make
|
[`make`]: https://www.gnu.org/software/make
|
||||||
[`sed`]: https://www.gnu.org/software/sed
|
[`sed`]: https://www.gnu.org/software/sed
|
||||||
[DAM]: https://kubernetes-sigs.github.io/kustomize/api-reference/glossary#declarative-application-management
|
[DAM]: https://kubernetes-sigs.github.io/kustomize/api-reference/glossary#declarative-application-management
|
||||||
[KEP]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-cli/0008-kustomize.md
|
[KEP]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-cli/2377-Kustomize/README.md
|
||||||
[Kubernetes Code of Conduct]: code-of-conduct.md
|
[Kubernetes Code of Conduct]: code-of-conduct.md
|
||||||
[applied]: https://kubernetes-sigs.github.io/kustomize/api-reference/glossary#apply
|
[applied]: https://kubernetes-sigs.github.io/kustomize/api-reference/glossary#apply
|
||||||
[base]: https://kubernetes-sigs.github.io/kustomize/api-reference/glossary#base
|
[base]: https://kubernetes-sigs.github.io/kustomize/api-reference/glossary#base
|
||||||
|
|||||||
@@ -27,16 +27,10 @@ func (p *AnnotationsTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
if len(p.Annotations) == 0 {
|
if len(p.Annotations) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, r := range m.Resources() {
|
return m.ApplyFilter(annotations.Filter{
|
||||||
err := r.ApplyFilter(annotations.Filter{
|
Annotations: p.Annotations,
|
||||||
Annotations: p.Annotations,
|
FsSlice: p.FieldSpecs,
|
||||||
FsSlice: p.FieldSpecs,
|
})
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAnnotationsTransformerPlugin() resmap.TransformerPlugin {
|
func NewAnnotationsTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
|||||||
@@ -267,6 +267,9 @@ func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string {
|
|||||||
if p.ReleaseName != "" {
|
if p.ReleaseName != "" {
|
||||||
args = append(args, p.ReleaseName)
|
args = append(args, p.ReleaseName)
|
||||||
}
|
}
|
||||||
|
if p.Namespace != "" {
|
||||||
|
args = append(args, "--namespace", p.Namespace)
|
||||||
|
}
|
||||||
args = append(args, filepath.Join(p.absChartHome(), p.Name))
|
args = append(args, filepath.Join(p.absChartHome(), p.Name))
|
||||||
if p.ValuesFile != "" {
|
if p.ValuesFile != "" {
|
||||||
args = append(args, "--values", p.ValuesFile)
|
args = append(args, "--values", p.ValuesFile)
|
||||||
@@ -277,6 +280,9 @@ func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string {
|
|||||||
// I've tried placing the flag before and after the name argument.
|
// I've tried placing the flag before and after the name argument.
|
||||||
args = append(args, "--generate-name")
|
args = append(args, "--generate-name")
|
||||||
}
|
}
|
||||||
|
if p.IncludeCRDs {
|
||||||
|
args = append(args, "--include-crds")
|
||||||
|
}
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
api/builtins/IAMPolicyGenerator.go
Normal file
33
api/builtins/IAMPolicyGenerator.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Code generated by pluginator on IAMPolicyGenerator; DO NOT EDIT.
|
||||||
|
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||||
|
|
||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/api/filters/iampolicygenerator"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IAMPolicyGeneratorPlugin struct {
|
||||||
|
types.IAMPolicyGeneratorArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IAMPolicyGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
|
||||||
|
p.IAMPolicyGeneratorArgs = types.IAMPolicyGeneratorArgs{}
|
||||||
|
err = yaml.Unmarshal(config, p)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *IAMPolicyGeneratorPlugin) Generate() (resmap.ResMap, error) {
|
||||||
|
r := resmap.New()
|
||||||
|
err := r.ApplyFilter(iampolicygenerator.Filter{
|
||||||
|
IAMPolicyGenerator: p.IAMPolicyGeneratorArgs,
|
||||||
|
})
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIAMPolicyGeneratorPlugin() resmap.GeneratorPlugin {
|
||||||
|
return &IAMPolicyGeneratorPlugin{}
|
||||||
|
}
|
||||||
@@ -25,24 +25,15 @@ func (p *ImageTagTransformerPlugin) Config(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error {
|
func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||||
for _, r := range m.Resources() {
|
if err := m.ApplyFilter(imagetag.LegacyFilter{
|
||||||
// traverse all fields at first
|
ImageTag: p.ImageTag,
|
||||||
err := r.ApplyFilter(imagetag.LegacyFilter{
|
}); err != nil {
|
||||||
ImageTag: p.ImageTag,
|
return err
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// then use user specified field specs
|
|
||||||
err = r.ApplyFilter(imagetag.Filter{
|
|
||||||
ImageTag: p.ImageTag,
|
|
||||||
FsSlice: p.FieldSpecs,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return m.ApplyFilter(imagetag.Filter{
|
||||||
|
ImageTag: p.ImageTag,
|
||||||
|
FsSlice: p.FieldSpecs,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewImageTagTransformerPlugin() resmap.TransformerPlugin {
|
func NewImageTagTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
|||||||
@@ -27,16 +27,10 @@ func (p *LabelTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
if len(p.Labels) == 0 {
|
if len(p.Labels) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, r := range m.Resources() {
|
return m.ApplyFilter(labels.Filter{
|
||||||
err := r.ApplyFilter(labels.Filter{
|
Labels: p.Labels,
|
||||||
Labels: p.Labels,
|
FsSlice: p.FieldSpecs,
|
||||||
FsSlice: p.FieldSpecs,
|
})
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLabelTransformerPlugin() resmap.TransformerPlugin {
|
func NewLabelTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, r := range m.Resources() {
|
for _, r := range m.Resources() {
|
||||||
if r.IsEmpty() {
|
if r.IsNilOrEmpty() {
|
||||||
// Don't mutate empty objects?
|
// Don't mutate empty objects?
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ func (p *PatchTransformerPlugin) Config(
|
|||||||
if errSM == nil {
|
if errSM == nil {
|
||||||
p.loadedPatch = patchSM
|
p.loadedPatch = patchSM
|
||||||
if p.Options["allowNameChange"] {
|
if p.Options["allowNameChange"] {
|
||||||
p.loadedPatch.SetAllowNameChange("true")
|
p.loadedPatch.AllowNameChange()
|
||||||
}
|
}
|
||||||
if p.Options["allowKindChange"] {
|
if p.Options["allowKindChange"] {
|
||||||
p.loadedPatch.SetAllowKindChange("true")
|
p.loadedPatch.AllowKindChange()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.decodedPatch = patchJson
|
p.decodedPatch = patchJson
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
|
"sigs.k8s.io/kustomize/api/filters/prefixsuffix"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -73,12 +73,11 @@ func (p *PrefixSuffixTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
r.StorePreviousId()
|
r.StorePreviousId()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := r.ApplyFilter(prefixsuffix.Filter{
|
if err := r.ApplyFilter(prefixsuffix.Filter{
|
||||||
Prefix: p.Prefix,
|
Prefix: p.Prefix,
|
||||||
Suffix: p.Suffix,
|
Suffix: p.Suffix,
|
||||||
FieldSpec: fs,
|
FieldSpec: fs,
|
||||||
})
|
}); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/filters/replacement"
|
"sigs.k8s.io/kustomize/api/filters/replacement"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -50,14 +49,9 @@ func (p *ReplacementTransformerPlugin) Config(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *ReplacementTransformerPlugin) Transform(m resmap.ResMap) (err error) {
|
func (p *ReplacementTransformerPlugin) Transform(m resmap.ResMap) (err error) {
|
||||||
var nodes []*kyaml.RNode
|
return m.ApplyFilter(replacement.Filter{
|
||||||
for _, r := range m.Resources() {
|
|
||||||
nodes = append(nodes, r.Node())
|
|
||||||
}
|
|
||||||
_, err = replacement.Filter{
|
|
||||||
Replacements: p.Replacements,
|
Replacements: p.Replacements,
|
||||||
}.Filter(nodes)
|
})
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReplacementTransformerPlugin() resmap.TransformerPlugin {
|
func NewReplacementTransformerPlugin() resmap.TransformerPlugin {
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/replicacount"
|
"sigs.k8s.io/kustomize/api/filters/replicacount"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
61
api/filesys/filesys.go
Normal file
61
api/filesys/filesys.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2021 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// Package filesys provides a file system abstraction,
|
||||||
|
// a subset of that provided by golang.org/pkg/os,
|
||||||
|
// with an on-disk and in-memory representation.
|
||||||
|
//
|
||||||
|
// Deprecated: use sigs.k8s.io/kustomize/kyaml/filesys instead.
|
||||||
|
package filesys
|
||||||
|
|
||||||
|
import "sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Separator is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.Separator.
|
||||||
|
Separator = filesys.Separator
|
||||||
|
// SelfDir is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.SelfDir.
|
||||||
|
SelfDir = filesys.SelfDir
|
||||||
|
// ParentDir is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.ParentDir.
|
||||||
|
ParentDir = filesys.ParentDir
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// FileSystem is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.FileSystem.
|
||||||
|
FileSystem = filesys.FileSystem
|
||||||
|
// FileSystemOrOnDisk is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.FileSystemOrOnDisk.
|
||||||
|
FileSystemOrOnDisk = filesys.FileSystemOrOnDisk
|
||||||
|
// ConfirmedDir is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.ConfirmedDir.
|
||||||
|
ConfirmedDir = filesys.ConfirmedDir
|
||||||
|
)
|
||||||
|
|
||||||
|
// MakeEmptyDirInMemory is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.MakeEmptyDirInMemory.
|
||||||
|
func MakeEmptyDirInMemory() FileSystem { return filesys.MakeEmptyDirInMemory() }
|
||||||
|
|
||||||
|
// MakeFsInMemory is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.MakeFsInMemory.
|
||||||
|
func MakeFsInMemory() FileSystem { return filesys.MakeFsInMemory() }
|
||||||
|
|
||||||
|
// MakeFsOnDisk is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.MakeFsOnDisk.
|
||||||
|
func MakeFsOnDisk() FileSystem { return filesys.MakeFsOnDisk() }
|
||||||
|
|
||||||
|
// NewTmpConfirmedDir is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.NewTmpConfirmedDir.
|
||||||
|
func NewTmpConfirmedDir() (filesys.ConfirmedDir, error) { return filesys.NewTmpConfirmedDir() }
|
||||||
|
|
||||||
|
// RootedPath is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.RootedPath.
|
||||||
|
func RootedPath(elem ...string) string { return filesys.RootedPath(elem...) }
|
||||||
|
|
||||||
|
// StripTrailingSeps is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.StripTrailingSeps.
|
||||||
|
func StripTrailingSeps(s string) string { return filesys.StripTrailingSeps(s) }
|
||||||
|
|
||||||
|
// StripLeadingSeps is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.StripLeadingSeps.
|
||||||
|
func StripLeadingSeps(s string) string { return filesys.StripLeadingSeps(s) }
|
||||||
|
|
||||||
|
// PathSplit is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.PathSplit.
|
||||||
|
func PathSplit(incoming string) []string { return filesys.PathSplit(incoming) }
|
||||||
|
|
||||||
|
// PathJoin is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.PathJoin.
|
||||||
|
func PathJoin(incoming []string) string { return filesys.PathJoin(incoming) }
|
||||||
|
|
||||||
|
// InsertPathPart is deprecated, use sigs.k8s.io/kustomize/kyaml/filesys.InsertPathPart.
|
||||||
|
func InsertPathPart(path string, pos int, part string) string {
|
||||||
|
return filesys.InsertPathPart(path, pos, part)
|
||||||
|
}
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// Package filesys provides a file system abstraction layer.
|
|
||||||
package filesys
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
Separator = string(filepath.Separator)
|
|
||||||
SelfDir = "."
|
|
||||||
ParentDir = ".."
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileSystem groups basic os filesystem methods.
|
|
||||||
// It's supposed be functional subset of https://golang.org/pkg/os
|
|
||||||
type FileSystem interface {
|
|
||||||
// Create a file.
|
|
||||||
Create(path string) (File, error)
|
|
||||||
// MkDir makes a directory.
|
|
||||||
Mkdir(path string) error
|
|
||||||
// MkDirAll makes a directory path, creating intervening directories.
|
|
||||||
MkdirAll(path string) error
|
|
||||||
// RemoveAll removes path and any children it contains.
|
|
||||||
RemoveAll(path string) error
|
|
||||||
// Open opens the named file for reading.
|
|
||||||
Open(path string) (File, error)
|
|
||||||
// IsDir returns true if the path is a directory.
|
|
||||||
IsDir(path string) bool
|
|
||||||
// CleanedAbs converts the given path into a
|
|
||||||
// directory and a file name, where the directory
|
|
||||||
// is represented as a ConfirmedDir and all that implies.
|
|
||||||
// If the entire path is a directory, the file component
|
|
||||||
// is an empty string.
|
|
||||||
CleanedAbs(path string) (ConfirmedDir, string, error)
|
|
||||||
// Exists is true if the path exists in the file system.
|
|
||||||
Exists(path string) bool
|
|
||||||
// Glob returns the list of matching files,
|
|
||||||
// emulating https://golang.org/pkg/path/filepath/#Glob
|
|
||||||
Glob(pattern string) ([]string, error)
|
|
||||||
// ReadFile returns the contents of the file at the given path.
|
|
||||||
ReadFile(path string) ([]byte, error)
|
|
||||||
// WriteFile writes the data to a file at the given path,
|
|
||||||
// overwriting anything that's already there.
|
|
||||||
WriteFile(path string, data []byte) error
|
|
||||||
// Walk walks the file system with the given WalkFunc.
|
|
||||||
Walk(path string, walkFn filepath.WalkFunc) error
|
|
||||||
}
|
|
||||||
5
api/filters/doc.go
Normal file
5
api/filters/doc.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package filters
|
||||||
|
|
||||||
|
// Package filters collects various implementations
|
||||||
|
// sigs.k8s.io/kustomize/kyaml/kio.Filter used by kustomize
|
||||||
|
// transformers to modify kubernetes objects.
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/internal/utils"
|
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -45,12 +46,11 @@ type Filter struct {
|
|||||||
|
|
||||||
func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
|
func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
|
||||||
// check if the FieldSpec applies to the object
|
// check if the FieldSpec applies to the object
|
||||||
if match, err := isMatchGVK(fltr.FieldSpec, obj); !match || err != nil {
|
if match := isMatchGVK(fltr.FieldSpec, obj); !match {
|
||||||
return obj, errors.Wrap(err)
|
return obj, nil
|
||||||
}
|
}
|
||||||
fltr.path = utils.PathSplitter(fltr.FieldSpec.Path)
|
fltr.path = utils.PathSplitter(fltr.FieldSpec.Path, "/")
|
||||||
err := fltr.filter(obj)
|
if err := fltr.filter(obj); err != nil {
|
||||||
if err != nil {
|
|
||||||
s, _ := obj.String()
|
s, _ := obj.String()
|
||||||
return nil, errors.WrapPrefixf(err,
|
return nil, errors.WrapPrefixf(err,
|
||||||
"considering field '%s' of object\n%v", fltr.FieldSpec.Path, s)
|
"considering field '%s' of object\n%v", fltr.FieldSpec.Path, s)
|
||||||
@@ -158,28 +158,24 @@ func isSequenceField(name string) (string, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// isMatchGVK returns true if the fs.GVK matches the obj GVK.
|
// isMatchGVK returns true if the fs.GVK matches the obj GVK.
|
||||||
func isMatchGVK(fs types.FieldSpec, obj *yaml.RNode) (bool, error) {
|
func isMatchGVK(fs types.FieldSpec, obj *yaml.RNode) bool {
|
||||||
meta, err := obj.GetMeta()
|
if kind := obj.GetKind(); fs.Kind != "" && fs.Kind != kind {
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if fs.Kind != "" && fs.Kind != meta.Kind {
|
|
||||||
// kind doesn't match
|
// kind doesn't match
|
||||||
return false, err
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the group and version from the apiVersion field
|
// parse the group and version from the apiVersion field
|
||||||
group, version := parseGV(meta.APIVersion)
|
group, version := resid.ParseGroupVersion(obj.GetApiVersion())
|
||||||
|
|
||||||
if fs.Group != "" && fs.Group != group {
|
if fs.Group != "" && fs.Group != group {
|
||||||
// group doesn't match
|
// group doesn't match
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if fs.Version != "" && fs.Version != version {
|
if fs.Version != "" && fs.Version != version {
|
||||||
// version doesn't match
|
// version doesn't match
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,11 @@ xxx:
|
|||||||
"empty path": {
|
"empty path": {
|
||||||
fieldSpec: `
|
fieldSpec: `
|
||||||
group: foo
|
group: foo
|
||||||
|
version: v1
|
||||||
kind: Bar
|
kind: Bar
|
||||||
`,
|
`,
|
||||||
input: `
|
input: `
|
||||||
apiVersion: foo
|
apiVersion: foo/v1
|
||||||
kind: Bar
|
kind: Bar
|
||||||
xxx:
|
xxx:
|
||||||
`,
|
`,
|
||||||
@@ -59,7 +60,7 @@ kind: Bar
|
|||||||
xxx:
|
xxx:
|
||||||
`,
|
`,
|
||||||
error: `considering field '' of object
|
error: `considering field '' of object
|
||||||
apiVersion: foo
|
apiVersion: foo/v1
|
||||||
kind: Bar
|
kind: Bar
|
||||||
xxx:
|
xxx:
|
||||||
: cannot set or create an empty field name`,
|
: cannot set or create an empty field name`,
|
||||||
@@ -195,11 +196,14 @@ kind: Bar
|
|||||||
input: `
|
input: `
|
||||||
a:
|
a:
|
||||||
b: c
|
b: c
|
||||||
|
`,
|
||||||
|
expected: `
|
||||||
|
a:
|
||||||
|
b: c
|
||||||
`,
|
`,
|
||||||
filter: fieldspec.Filter{
|
filter: fieldspec.Filter{
|
||||||
SetValue: filtersutil.SetScalar("e"),
|
SetValue: filtersutil.SetScalar("e"),
|
||||||
},
|
},
|
||||||
error: "missing Resource metadata",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"miss-match-type": {
|
"miss-match-type": {
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
package fieldspec
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
package fieldspec
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
api/filters/iampolicygenerator/doc.go
Normal file
3
api/filters/iampolicygenerator/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package gkesagenerator contains a kio.Filter that that generates a
|
||||||
|
// iampolicy-related resources for a given cloud provider
|
||||||
|
package iampolicygenerator
|
||||||
46
api/filters/iampolicygenerator/example_test.go
Normal file
46
api/filters/iampolicygenerator/example_test.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2021 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package iampolicygenerator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleFilter() {
|
||||||
|
f := Filter{}
|
||||||
|
var err = yaml.Unmarshal([]byte(`
|
||||||
|
cloud: gke
|
||||||
|
kubernetesService:
|
||||||
|
namespace: k8s-namespace
|
||||||
|
name: k8s-sa-name
|
||||||
|
serviceAccount:
|
||||||
|
name: gsa-name
|
||||||
|
projectId: project-id
|
||||||
|
`), &f)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = kio.Pipeline{
|
||||||
|
Inputs: []kio.Reader{},
|
||||||
|
Filters: []kio.Filter{f},
|
||||||
|
Outputs: []kio.Writer{kio.ByteWriter{Writer: os.Stdout}},
|
||||||
|
}.Execute()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// apiVersion: v1
|
||||||
|
// kind: ServiceAccount
|
||||||
|
// metadata:
|
||||||
|
// annotations:
|
||||||
|
// iam.gke.io/gcp-service-account: gsa-name@project-id.iam.gserviceaccount.com
|
||||||
|
// name: k8s-sa-name
|
||||||
|
// namespace: k8s-namespace
|
||||||
|
}
|
||||||
55
api/filters/iampolicygenerator/iampolicygenerator.go
Normal file
55
api/filters/iampolicygenerator/iampolicygenerator.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// Copyright 2021 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package iampolicygenerator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Filter struct {
|
||||||
|
IAMPolicyGenerator types.IAMPolicyGeneratorArgs `json:",inline,omitempty" yaml:",inline,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter adds a GKE service account object to nodes
|
||||||
|
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
|
switch f.IAMPolicyGenerator.Cloud {
|
||||||
|
case types.GKE:
|
||||||
|
IAMPolicyResources, err := f.generateGkeIAMPolicyResources()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nodes = append(nodes, IAMPolicyResources...)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("cloud provider %s not supported yet", f.IAMPolicyGenerator.Cloud)
|
||||||
|
}
|
||||||
|
return nodes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f Filter) generateGkeIAMPolicyResources() ([]*yaml.RNode, error) {
|
||||||
|
var result []*yaml.RNode
|
||||||
|
input := fmt.Sprintf(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
iam.gke.io/gcp-service-account: %s@%s.iam.gserviceaccount.com
|
||||||
|
name: %s
|
||||||
|
`, f.IAMPolicyGenerator.ServiceAccount.Name,
|
||||||
|
f.IAMPolicyGenerator.ProjectId,
|
||||||
|
f.IAMPolicyGenerator.KubernetesService.Name)
|
||||||
|
|
||||||
|
if f.IAMPolicyGenerator.Namespace != "" {
|
||||||
|
input = input + fmt.Sprintf("\n namespace: %s", f.IAMPolicyGenerator.Namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
sa, err := yaml.Parse(input)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return append(result, sa), nil
|
||||||
|
}
|
||||||
75
api/filters/iampolicygenerator/iampolicygenerator_test.go
Normal file
75
api/filters/iampolicygenerator/iampolicygenerator_test.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2021 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package iampolicygenerator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
filtertest "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilter(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
args types.IAMPolicyGeneratorArgs
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
"with namespace": {
|
||||||
|
args: types.IAMPolicyGeneratorArgs{
|
||||||
|
Cloud: types.GKE,
|
||||||
|
KubernetesService: types.KubernetesService{
|
||||||
|
Namespace: "k8s-namespace",
|
||||||
|
Name: "k8s-sa-name",
|
||||||
|
},
|
||||||
|
ServiceAccount: types.ServiceAccount{
|
||||||
|
Name: "gsa-name",
|
||||||
|
ProjectId: "project-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
iam.gke.io/gcp-service-account: gsa-name@project-id.iam.gserviceaccount.com
|
||||||
|
name: k8s-sa-name
|
||||||
|
namespace: k8s-namespace
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
"without namespace": {
|
||||||
|
args: types.IAMPolicyGeneratorArgs{
|
||||||
|
Cloud: types.GKE,
|
||||||
|
KubernetesService: types.KubernetesService{
|
||||||
|
Name: "k8s-sa-name",
|
||||||
|
},
|
||||||
|
ServiceAccount: types.ServiceAccount{
|
||||||
|
Name: "gsa-name",
|
||||||
|
ProjectId: "project-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
iam.gke.io/gcp-service-account: gsa-name@project-id.iam.gserviceaccount.com
|
||||||
|
name: k8s-sa-name
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tn, tc := range testCases {
|
||||||
|
t.Run(tn, func(t *testing.T) {
|
||||||
|
f := Filter{
|
||||||
|
IAMPolicyGenerator: tc.args,
|
||||||
|
}
|
||||||
|
actual := filtertest.RunFilter(t, "", f)
|
||||||
|
if !assert.Equal(t, strings.TrimSpace(tc.expected), strings.TrimSpace(actual)) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
package imagetag
|
package imagetag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
@@ -74,7 +75,7 @@ func (f findFieldsFilter) walk(node *yaml.RNode) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
key := n.Key.YNode().Value
|
key := n.Key.YNode().Value
|
||||||
if contains(f.fields, key) {
|
if utils.StringSliceContains(f.fields, key) {
|
||||||
return f.fieldCallback(n.Value)
|
return f.fieldCallback(n.Value)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -87,15 +88,6 @@ func (f findFieldsFilter) walk(node *yaml.RNode) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func contains(slice []string, str string) bool {
|
|
||||||
for _, s := range slice {
|
|
||||||
if s == str {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkImageTagsFn(imageTag types.Image) fieldCallback {
|
func checkImageTagsFn(imageTag types.Image) fieldCallback {
|
||||||
return func(node *yaml.RNode) error {
|
return func(node *yaml.RNode) error {
|
||||||
if node.YNode().Kind != yaml.SequenceNode {
|
if node.YNode().Kind != yaml.SequenceNode {
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLabels_Filter(t *testing.T) {
|
func TestLabels_Filter(t *testing.T) {
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/api/filters/fieldspec"
|
"sigs.k8s.io/kustomize/api/filters/fieldspec"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ func (f Filter) recordTheReferral(referral *resource.Resource) {
|
|||||||
|
|
||||||
// getRoleRefGvk returns a Gvk in the roleRef field. Return error
|
// getRoleRefGvk returns a Gvk in the roleRef field. Return error
|
||||||
// if the roleRef, roleRef/apiGroup or roleRef/kind is missing.
|
// if the roleRef, roleRef/apiGroup or roleRef/kind is missing.
|
||||||
func getRoleRefGvk(n *yaml.RNode) (*resid.Gvk, error) {
|
func getRoleRefGvk(n *resource.Resource) (*resid.Gvk, error) {
|
||||||
roleRef, err := n.Pipe(yaml.Lookup("roleRef"))
|
roleRef, err := n.Pipe(yaml.Lookup("roleRef"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -257,8 +257,7 @@ func previousIdSelectedByGvk(gvk *resid.Gvk) sieveFunc {
|
|||||||
|
|
||||||
// If the we are updating a 'roleRef/name' field, the 'apiGroup' and 'kind'
|
// If the we are updating a 'roleRef/name' field, the 'apiGroup' and 'kind'
|
||||||
// fields in the same 'roleRef' map must be considered.
|
// fields in the same 'roleRef' map must be considered.
|
||||||
// If either object is cluster-scoped (!IsNamespaceableKind), there
|
// If either object is cluster-scoped, there can be a referral.
|
||||||
// can be a referral.
|
|
||||||
// E.g. a RoleBinding (which exists in a namespace) can refer
|
// E.g. a RoleBinding (which exists in a namespace) can refer
|
||||||
// to a ClusterRole (cluster-scoped) object.
|
// to a ClusterRole (cluster-scoped) object.
|
||||||
// https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole
|
// https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole
|
||||||
@@ -270,7 +269,7 @@ func (f Filter) roleRefFilter() sieveFunc {
|
|||||||
if !strings.HasSuffix(f.NameFieldToUpdate.Path, "roleRef/name") {
|
if !strings.HasSuffix(f.NameFieldToUpdate.Path, "roleRef/name") {
|
||||||
return acceptAll
|
return acceptAll
|
||||||
}
|
}
|
||||||
roleRefGvk, err := getRoleRefGvk(f.Referrer.AsRNode())
|
roleRefGvk, err := getRoleRefGvk(f.Referrer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return acceptAll
|
return acceptAll
|
||||||
}
|
}
|
||||||
@@ -285,12 +284,12 @@ func prefixSuffixEquals(other resource.ResCtx) sieveFunc {
|
|||||||
|
|
||||||
func (f Filter) sameCurrentNamespaceAsReferrer() sieveFunc {
|
func (f Filter) sameCurrentNamespaceAsReferrer() sieveFunc {
|
||||||
referrerCurId := f.Referrer.CurId()
|
referrerCurId := f.Referrer.CurId()
|
||||||
if !referrerCurId.IsNamespaceableKind() {
|
if referrerCurId.IsClusterScoped() {
|
||||||
// If the referrer is cluster-scoped, let anything through.
|
// If the referrer is cluster-scoped, let anything through.
|
||||||
return acceptAll
|
return acceptAll
|
||||||
}
|
}
|
||||||
return func(r *resource.Resource) bool {
|
return func(r *resource.Resource) bool {
|
||||||
if !r.CurId().IsNamespaceableKind() {
|
if r.CurId().IsClusterScoped() {
|
||||||
// Allow cluster-scoped through.
|
// Allow cluster-scoped through.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/provider"
|
"sigs.k8s.io/kustomize/api/provider"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
filtertest_test "sigs.k8s.io/kustomize/api/testutils/filtertest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNamerefFilter(t *testing.T) {
|
func TestNamerefFilter(t *testing.T) {
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
package namespace
|
package namespace
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/api/filters/fieldspec"
|
|
||||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
||||||
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
"sigs.k8s.io/kustomize/api/filters/fsslice"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -54,16 +54,11 @@ func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
// hacks applies the namespace transforms that are hardcoded rather
|
// hacks applies the namespace transforms that are hardcoded rather
|
||||||
// than specified through FieldSpecs.
|
// than specified through FieldSpecs.
|
||||||
func (ns Filter) hacks(obj *yaml.RNode) error {
|
func (ns Filter) hacks(obj *yaml.RNode) error {
|
||||||
meta, err := obj.GetMeta()
|
gvk := resid.GvkFromNode(obj)
|
||||||
if err != nil {
|
if err := ns.metaNamespaceHack(obj, gvk); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return ns.roleBindingHack(obj, gvk)
|
||||||
if err := ns.metaNamespaceHack(obj, meta); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ns.roleBindingHack(obj, meta)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// metaNamespaceHack is a hack for implementing the namespace transform
|
// metaNamespaceHack is a hack for implementing the namespace transform
|
||||||
@@ -74,9 +69,8 @@ func (ns Filter) hacks(obj *yaml.RNode) error {
|
|||||||
// This hack should be updated to allow individual resources to specify
|
// This hack should be updated to allow individual resources to specify
|
||||||
// if they are cluster scoped through either an annotation on the resources,
|
// if they are cluster scoped through either an annotation on the resources,
|
||||||
// or through inlined OpenAPI on the resource as a YAML comment.
|
// or through inlined OpenAPI on the resource as a YAML comment.
|
||||||
func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) error {
|
func (ns Filter) metaNamespaceHack(obj *yaml.RNode, gvk resid.Gvk) error {
|
||||||
gvk := fieldspec.GetGVK(meta)
|
if gvk.IsClusterScoped() {
|
||||||
if !gvk.IsNamespaceableKind() {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
f := fsslice.Filter{
|
f := fsslice.Filter{
|
||||||
@@ -104,8 +98,8 @@ func (ns Filter) metaNamespaceHack(obj *yaml.RNode, meta yaml.ResourceMeta) erro
|
|||||||
// ...
|
// ...
|
||||||
// - name: "something-else" # this will not have the namespace set
|
// - name: "something-else" # this will not have the namespace set
|
||||||
// ...
|
// ...
|
||||||
func (ns Filter) roleBindingHack(obj *yaml.RNode, meta yaml.ResourceMeta) error {
|
func (ns Filter) roleBindingHack(obj *yaml.RNode, gvk resid.Gvk) error {
|
||||||
if meta.Kind != roleBindingKind && meta.Kind != clusterRoleBindingKind {
|
if gvk.Kind != roleBindingKind && gvk.Kind != clusterRoleBindingKind {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -43,11 +44,17 @@ func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targets []*types.T
|
|||||||
t.FieldPaths = []string{types.DefaultReplacementFieldPath}
|
t.FieldPaths = []string{types.DefaultReplacementFieldPath}
|
||||||
}
|
}
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
id := makeResId(n)
|
ids, err := utils.MakeResIds(n)
|
||||||
if id.IsSelectedBy(t.Select.ResId) && !rejectId(t.Reject, id) {
|
if err != nil {
|
||||||
err := applyToNode(n, value, t)
|
return nil, err
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
for _, id := range ids {
|
||||||
|
if id.IsSelectedBy(t.Select.ResId) && !rejectId(t.Reject, &id) {
|
||||||
|
err := applyToNode(n, value, t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +73,7 @@ func rejectId(rejects []*types.Selector, id *resid.ResId) bool {
|
|||||||
|
|
||||||
func applyToNode(node *yaml.RNode, value *yaml.RNode, target *types.TargetSelector) error {
|
func applyToNode(node *yaml.RNode, value *yaml.RNode, target *types.TargetSelector) error {
|
||||||
for _, fp := range target.FieldPaths {
|
for _, fp := range target.FieldPaths {
|
||||||
fieldPath := strings.Split(fp, ".")
|
fieldPath := utils.SmarterPathSplitter(fp, ".")
|
||||||
var t *yaml.RNode
|
var t *yaml.RNode
|
||||||
var err error
|
var err error
|
||||||
if target.Options != nil && target.Options.Create {
|
if target.Options != nil && target.Options.Create {
|
||||||
@@ -87,12 +94,11 @@ func applyToNode(node *yaml.RNode, value *yaml.RNode, target *types.TargetSelect
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setTargetValue(options *types.FieldOptions, t *yaml.RNode, value *yaml.RNode) error {
|
func setTargetValue(options *types.FieldOptions, t *yaml.RNode, value *yaml.RNode) error {
|
||||||
|
value = value.Copy()
|
||||||
if options != nil && options.Delimiter != "" {
|
if options != nil && options.Delimiter != "" {
|
||||||
|
|
||||||
if t.YNode().Kind != yaml.ScalarNode {
|
if t.YNode().Kind != yaml.ScalarNode {
|
||||||
return fmt.Errorf("delimiter option can only be used with scalar nodes")
|
return fmt.Errorf("delimiter option can only be used with scalar nodes")
|
||||||
}
|
}
|
||||||
|
|
||||||
tv := strings.Split(t.YNode().Value, options.Delimiter)
|
tv := strings.Split(t.YNode().Value, options.Delimiter)
|
||||||
v := yaml.GetValue(value)
|
v := yaml.GetValue(value)
|
||||||
// TODO: Add a way to remove an element
|
// TODO: Add a way to remove an element
|
||||||
@@ -119,7 +125,7 @@ func getReplacement(nodes []*yaml.RNode, r *types.Replacement) (*yaml.RNode, err
|
|||||||
if r.Source.FieldPath == "" {
|
if r.Source.FieldPath == "" {
|
||||||
r.Source.FieldPath = types.DefaultReplacementFieldPath
|
r.Source.FieldPath = types.DefaultReplacementFieldPath
|
||||||
}
|
}
|
||||||
fieldPath := strings.Split(r.Source.FieldPath, ".")
|
fieldPath := utils.SmarterPathSplitter(r.Source.FieldPath, ".")
|
||||||
|
|
||||||
rn, err := source.Pipe(yaml.Lookup(fieldPath...))
|
rn, err := source.Pipe(yaml.Lookup(fieldPath...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -152,12 +158,19 @@ func getRefinedValue(options *types.FieldOptions, rn *yaml.RNode) (*yaml.RNode,
|
|||||||
func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yaml.RNode, error) {
|
func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yaml.RNode, error) {
|
||||||
var matches []*yaml.RNode
|
var matches []*yaml.RNode
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
if makeResId(n).IsSelectedBy(selector.ResId) {
|
ids, err := utils.MakeResIds(n)
|
||||||
if len(matches) > 0 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(
|
return nil, err
|
||||||
"multiple matches for selector %s", selector)
|
}
|
||||||
|
for _, id := range ids {
|
||||||
|
if id.IsSelectedBy(selector.ResId) {
|
||||||
|
if len(matches) > 0 {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"multiple matches for selector %s", selector)
|
||||||
|
}
|
||||||
|
matches = append(matches, n)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
matches = append(matches, n)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(matches) == 0 {
|
if len(matches) == 0 {
|
||||||
@@ -165,22 +178,3 @@ func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yam
|
|||||||
}
|
}
|
||||||
return matches[0], nil
|
return matches[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeResId makes a ResId from an RNode.
|
|
||||||
func makeResId(n *yaml.RNode) *resid.ResId {
|
|
||||||
ns, err := n.GetNamespace()
|
|
||||||
if err != nil {
|
|
||||||
// Resource has no metadata (no apiVersion, kind, nor metadata field).
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
apiVersion := n.Field(yaml.APIVersionField)
|
|
||||||
var group, version string
|
|
||||||
if apiVersion != nil {
|
|
||||||
group, version = resid.ParseGroupVersion(yaml.GetValue(apiVersion.Value))
|
|
||||||
}
|
|
||||||
return &resid.ResId{
|
|
||||||
Gvk: resid.Gvk{Group: group, Version: version, Kind: n.GetKind()},
|
|
||||||
Name: n.GetName(),
|
|
||||||
Namespace: ns,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1338,6 +1338,224 @@ spec:
|
|||||||
`,
|
`,
|
||||||
expectedErr: "delimiter option can only be used with scalar nodes",
|
expectedErr: "delimiter option can only be used with scalar nodes",
|
||||||
},
|
},
|
||||||
|
"mapping value contains '.' character": {
|
||||||
|
input: `apiVersion: v1
|
||||||
|
kind: Custom
|
||||||
|
metadata:
|
||||||
|
name: custom
|
||||||
|
annotations:
|
||||||
|
a.b.c/d-e: source
|
||||||
|
f.g.h/i-j: target
|
||||||
|
`,
|
||||||
|
replacements: `replacements:
|
||||||
|
- source:
|
||||||
|
name: custom
|
||||||
|
fieldPath: metadata.annotations.[a.b.c/d-e]
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
name: custom
|
||||||
|
fieldPaths:
|
||||||
|
- metadata.annotations.[f.g.h/i-j]
|
||||||
|
`,
|
||||||
|
expected: `apiVersion: v1
|
||||||
|
kind: Custom
|
||||||
|
metadata:
|
||||||
|
name: custom
|
||||||
|
annotations:
|
||||||
|
a.b.c/d-e: source
|
||||||
|
f.g.h/i-j: source
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
"list index contains '.' character": {
|
||||||
|
input: `apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: source
|
||||||
|
data:
|
||||||
|
value: example
|
||||||
|
---
|
||||||
|
apiVersion: kubernetes-client.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: some-secret
|
||||||
|
spec:
|
||||||
|
backendType: secretsManager
|
||||||
|
data:
|
||||||
|
- key: some-prefix-replaceme
|
||||||
|
name: .first
|
||||||
|
version: latest
|
||||||
|
property: first
|
||||||
|
- key: some-prefix-replaceme
|
||||||
|
name: second
|
||||||
|
version: latest
|
||||||
|
property: second
|
||||||
|
`,
|
||||||
|
replacements: `replacements:
|
||||||
|
- source:
|
||||||
|
kind: ConfigMap
|
||||||
|
version: v1
|
||||||
|
name: source
|
||||||
|
fieldPath: data.value
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
group: kubernetes-client.io
|
||||||
|
version: v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
name: some-secret
|
||||||
|
fieldPaths:
|
||||||
|
- spec.data.[name=.first].key
|
||||||
|
- spec.data.[name=second].key
|
||||||
|
options:
|
||||||
|
delimiter: "-"
|
||||||
|
index: 2
|
||||||
|
`,
|
||||||
|
expected: `apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: source
|
||||||
|
data:
|
||||||
|
value: example
|
||||||
|
---
|
||||||
|
apiVersion: kubernetes-client.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: some-secret
|
||||||
|
spec:
|
||||||
|
backendType: secretsManager
|
||||||
|
data:
|
||||||
|
- key: some-prefix-example
|
||||||
|
name: .first
|
||||||
|
version: latest
|
||||||
|
property: first
|
||||||
|
- key: some-prefix-example
|
||||||
|
name: second
|
||||||
|
version: latest
|
||||||
|
property: second`,
|
||||||
|
},
|
||||||
|
"multiple field paths in target": {
|
||||||
|
input: `apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: source
|
||||||
|
data:
|
||||||
|
value: example
|
||||||
|
---
|
||||||
|
apiVersion: kubernetes-client.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: some-secret
|
||||||
|
spec:
|
||||||
|
backendType: secretsManager
|
||||||
|
data:
|
||||||
|
- key: some-prefix-replaceme
|
||||||
|
name: first
|
||||||
|
version: latest
|
||||||
|
property: first
|
||||||
|
- key: some-prefix-replaceme
|
||||||
|
name: second
|
||||||
|
version: latest
|
||||||
|
property: second
|
||||||
|
- key: some-prefix-replaceme
|
||||||
|
name: third
|
||||||
|
version: latest
|
||||||
|
property: third
|
||||||
|
`,
|
||||||
|
replacements: `replacements:
|
||||||
|
- source:
|
||||||
|
kind: ConfigMap
|
||||||
|
version: v1
|
||||||
|
name: source
|
||||||
|
fieldPath: data.value
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
group: kubernetes-client.io
|
||||||
|
version: v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
name: some-secret
|
||||||
|
fieldPaths:
|
||||||
|
- spec.data.0.key
|
||||||
|
- spec.data.1.key
|
||||||
|
- spec.data.2.key
|
||||||
|
options:
|
||||||
|
delimiter: "-"
|
||||||
|
index: 2
|
||||||
|
`,
|
||||||
|
expected: `apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: source
|
||||||
|
data:
|
||||||
|
value: example
|
||||||
|
---
|
||||||
|
apiVersion: kubernetes-client.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: some-secret
|
||||||
|
spec:
|
||||||
|
backendType: secretsManager
|
||||||
|
data:
|
||||||
|
- key: some-prefix-example
|
||||||
|
name: first
|
||||||
|
version: latest
|
||||||
|
property: first
|
||||||
|
- key: some-prefix-example
|
||||||
|
name: second
|
||||||
|
version: latest
|
||||||
|
property: second
|
||||||
|
- key: some-prefix-example
|
||||||
|
name: third
|
||||||
|
version: latest
|
||||||
|
property: third
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
"using a previous ID": {
|
||||||
|
input: `apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: pre-deploy
|
||||||
|
annotations:
|
||||||
|
internal.config.kubernetes.io/previousNames: deploy,deploy
|
||||||
|
internal.config.kubernetes.io/previousKinds: CronJob,Deployment
|
||||||
|
internal.config.kubernetes.io/previousNamespaces: default,default
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: postgres:1.8.0
|
||||||
|
name: postgresdb
|
||||||
|
`,
|
||||||
|
replacements: `replacements:
|
||||||
|
- source:
|
||||||
|
kind: CronJob
|
||||||
|
name: deploy
|
||||||
|
fieldPath: spec.template.spec.containers.0.image
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
kind: Deployment
|
||||||
|
name: deploy
|
||||||
|
fieldPaths:
|
||||||
|
- spec.template.spec.containers.1.image
|
||||||
|
`,
|
||||||
|
expected: `apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: pre-deploy
|
||||||
|
annotations:
|
||||||
|
internal.config.kubernetes.io/previousNames: deploy,deploy
|
||||||
|
internal.config.kubernetes.io/previousKinds: CronJob,Deployment
|
||||||
|
internal.config.kubernetes.io/previousNamespaces: default,default
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx-tagged
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: postgresdb
|
||||||
|
`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for tn, tc := range testCases {
|
for tn, tc := range testCases {
|
||||||
@@ -1353,7 +1571,7 @@ spec:
|
|||||||
t.Errorf("unexpected error: %s\n", err.Error())
|
t.Errorf("unexpected error: %s\n", err.Error())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, tc.expectedErr, err.Error()) {
|
if !assert.Contains(t, err.Error(), tc.expectedErr) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ package valueadd
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/api
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/evanphx/json-patch v4.5.0+incompatible
|
github.com/evanphx/json-patch v4.11.0+incompatible
|
||||||
github.com/go-errors/errors v1.0.1
|
github.com/go-errors/errors v1.0.1
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||||
github.com/imdario/mergo v0.3.5
|
github.com/imdario/mergo v0.3.5
|
||||||
@@ -11,8 +11,8 @@ require (
|
|||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e
|
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e
|
||||||
sigs.k8s.io/kustomize/kyaml v0.10.18
|
sigs.k8s.io/kustomize/kyaml v0.11.1
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
replace sigs.k8s.io/kustomize/kyaml => ../kyaml
|
||||||
|
|||||||
12
api/go.sum
12
api/go.sum
@@ -30,8 +30,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
|||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
|
github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
|
||||||
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
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/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 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||||
@@ -47,7 +47,6 @@ github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL9
|
|||||||
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
|
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/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/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
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.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
@@ -98,7 +97,6 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
|
|||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
|
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
|
||||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||||
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
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/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
@@ -216,19 +214,15 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
|
|||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
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.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.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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM=
|
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM=
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.10.18 h1:Cuf4KiVULTttfo/2Vls2H9fA7eH8Xll1w6RgGdL+tR8=
|
|
||||||
sigs.k8s.io/kustomize/kyaml v0.10.18/go.mod h1:h94DSoDbmnN4BTc6VTX7tGNGXZy29rbPo+R4jGMvA8U=
|
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -178,9 +178,12 @@ func loadCrdIntoConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if property.Ref.GetURL() != nil {
|
if property.Ref.GetURL() != nil {
|
||||||
loadCrdIntoConfig(
|
err = loadCrdIntoConfig(
|
||||||
theConfig, theGvk, theMap,
|
theConfig, theGvk, theMap,
|
||||||
property.Ref.String(), append(path, propName))
|
property.Ref.String(), append(path, propName))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"github.com/stretchr/testify/require"
|
||||||
. "sigs.k8s.io/kustomize/api/internal/accumulator"
|
. "sigs.k8s.io/kustomize/api/internal/accumulator"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/api/loader"
|
"sigs.k8s.io/kustomize/api/loader"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This defines two CRD's: Bee and MyKind.
|
// This defines two CRD's: Bee and MyKind.
|
||||||
@@ -162,16 +163,13 @@ func TestLoadCRDs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fSys := filesys.MakeFsInMemory()
|
fSys := filesys.MakeFsInMemory()
|
||||||
fSys.WriteFile("/testpath/crd.json", []byte(crdContent))
|
err := fSys.WriteFile("/testpath/crd.json", []byte(crdContent))
|
||||||
|
require.NoError(t, err)
|
||||||
ldr, err := loader.NewLoader(loader.RestrictionRootOnly, "/testpath", fSys)
|
ldr, err := loader.NewLoader(loader.RestrictionRootOnly, "/testpath", fSys)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unexpected error:%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
actualTc, err := LoadConfigFromCRDs(ldr, []string{"crd.json"})
|
actualTc, err := LoadConfigFromCRDs(ldr, []string{"crd.json"})
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unexpected error:%v", err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(actualTc, expectedTc) {
|
if !reflect.DeepEqual(actualTc, expectedTc) {
|
||||||
t.Fatalf("expected\n %v\n but got\n %v\n", expectedTc, actualTc)
|
t.Fatalf("expected\n %v\n but got\n %v\n", expectedTc, actualTc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import (
|
|||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/api/provider"
|
"sigs.k8s.io/kustomize/api/provider"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
const notEqualErrFmt = "expected (self) doesn't match actual (other): %v"
|
const notEqualErrFmt = "expected (self) doesn't match actual (other): %v"
|
||||||
@@ -885,9 +885,9 @@ func TestNameReferenceClusterWide(t *testing.T) {
|
|||||||
}).ResMap()
|
}).ResMap()
|
||||||
|
|
||||||
clusterRoleId := resid.NewResId(
|
clusterRoleId := resid.NewResId(
|
||||||
resid.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, modifiedname)
|
resid.NewGvk("rbac.authorization.k8s.io", "v1", "ClusterRole"), modifiedname)
|
||||||
clusterRoleBindingId := resid.NewResId(
|
clusterRoleBindingId := resid.NewResId(
|
||||||
resid.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, modifiedname)
|
resid.NewGvk("rbac.authorization.k8s.io", "v1", "ClusterRoleBinding"), modifiedname)
|
||||||
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
||||||
clusterRole.AppendRefBy(clusterRoleBindingId)
|
clusterRole.AppendRefBy(clusterRoleBindingId)
|
||||||
|
|
||||||
@@ -897,7 +897,9 @@ func TestNameReferenceClusterWide(t *testing.T) {
|
|||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expected.RemoveBuildAnnotations()
|
||||||
m.RemoveBuildAnnotations()
|
m.RemoveBuildAnnotations()
|
||||||
|
|
||||||
if err = expected.ErrorIfNotEqualLists(m); err != nil {
|
if err = expected.ErrorIfNotEqualLists(m); err != nil {
|
||||||
t.Fatalf(notEqualErrFmt, err)
|
t.Fatalf(notEqualErrFmt, err)
|
||||||
}
|
}
|
||||||
@@ -1012,9 +1014,11 @@ func TestNameReferenceNamespaceTransformation(t *testing.T) {
|
|||||||
}).ResMap()
|
}).ResMap()
|
||||||
|
|
||||||
clusterRoleId := resid.NewResId(
|
clusterRoleId := resid.NewResId(
|
||||||
resid.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, modifiedname)
|
resid.NewGvk("rbac.authorization.k8s.io", "v1", "ClusterRole"),
|
||||||
|
modifiedname)
|
||||||
clusterRoleBindingId := resid.NewResId(
|
clusterRoleBindingId := resid.NewResId(
|
||||||
resid.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, modifiedname)
|
resid.NewGvk("rbac.authorization.k8s.io", "v1", "ClusterRoleBinding"),
|
||||||
|
modifiedname)
|
||||||
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
clusterRole, _ := expected.GetByCurrentId(clusterRoleId)
|
||||||
clusterRole.AppendRefBy(clusterRoleBindingId)
|
clusterRole.AppendRefBy(clusterRoleBindingId)
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRefVarTransformer(t *testing.T) {
|
func TestRefVarTransformer(t *testing.T) {
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResAccumulator accumulates resources and the rules
|
// ResAccumulator accumulates resources and the rules
|
||||||
@@ -72,7 +72,7 @@ func (ra *ResAccumulator) MergeVars(incoming []types.Var) error {
|
|||||||
for _, v := range incoming {
|
for _, v := range incoming {
|
||||||
targetId := resid.NewResIdWithNamespace(v.ObjRef.GVK(), v.ObjRef.Name, v.ObjRef.Namespace)
|
targetId := resid.NewResIdWithNamespace(v.ObjRef.GVK(), v.ObjRef.Name, v.ObjRef.Namespace)
|
||||||
idMatcher := targetId.GvknEquals
|
idMatcher := targetId.GvknEquals
|
||||||
if targetId.Namespace != "" || !targetId.IsNamespaceableKind() {
|
if targetId.Namespace != "" || targetId.IsClusterScoped() {
|
||||||
// Preserve backward compatibility. An empty namespace means
|
// Preserve backward compatibility. An empty namespace means
|
||||||
// wildcard search on the namespace hence we still use GvknEquals
|
// wildcard search on the namespace hence we still use GvknEquals
|
||||||
idMatcher = targetId.Equals
|
idMatcher = targetId.Equals
|
||||||
@@ -107,6 +107,7 @@ func (ra *ResAccumulator) findVarValueFromResources(v types.Var) (interface{}, e
|
|||||||
for _, res := range ra.resMap.Resources() {
|
for _, res := range ra.resMap.Resources() {
|
||||||
for _, varName := range res.GetRefVarNames() {
|
for _, varName := range res.GetRefVarNames() {
|
||||||
if varName == v.Name {
|
if varName == v.Name {
|
||||||
|
//nolint: staticcheck
|
||||||
s, err := res.GetFieldValue(v.FieldRef.FieldPath)
|
s, err := res.GetFieldValue(v.FieldRef.FieldPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf(
|
return "", fmt.Errorf(
|
||||||
|
|||||||
@@ -10,14 +10,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
. "sigs.k8s.io/kustomize/api/internal/accumulator"
|
. "sigs.k8s.io/kustomize/api/internal/accumulator"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/api/provider"
|
"sigs.k8s.io/kustomize/api/provider"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeResAccumulator(t *testing.T) *ResAccumulator {
|
func makeResAccumulator(t *testing.T) *ResAccumulator {
|
||||||
@@ -224,20 +225,26 @@ func TestResolveVarConflicts(t *testing.T) {
|
|||||||
// create accumulators holding apparently conflicting vars that are not
|
// create accumulators holding apparently conflicting vars that are not
|
||||||
// actually in conflict because they point to the same concrete value.
|
// actually in conflict because they point to the same concrete value.
|
||||||
rm0 := resmap.New()
|
rm0 := resmap.New()
|
||||||
rm0.Append(rf.FromMap(fooAws))
|
err := rm0.Append(rf.FromMap(fooAws))
|
||||||
|
require.NoError(t, err)
|
||||||
ac0 := MakeEmptyAccumulator()
|
ac0 := MakeEmptyAccumulator()
|
||||||
ac0.AppendAll(rm0)
|
err = ac0.AppendAll(rm0)
|
||||||
ac0.MergeVars([]types.Var{varFoo})
|
require.NoError(t, err)
|
||||||
|
err = ac0.MergeVars([]types.Var{varFoo})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
rm1 := resmap.New()
|
rm1 := resmap.New()
|
||||||
rm1.Append(rf.FromMap(barAws))
|
err = rm1.Append(rf.FromMap(barAws))
|
||||||
|
require.NoError(t, err)
|
||||||
ac1 := MakeEmptyAccumulator()
|
ac1 := MakeEmptyAccumulator()
|
||||||
ac1.AppendAll(rm1)
|
err = ac1.AppendAll(rm1)
|
||||||
ac1.MergeVars([]types.Var{varBar})
|
require.NoError(t, err)
|
||||||
|
err = ac1.MergeVars([]types.Var{varBar})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// validate that two vars of the same name which reference the same concrete
|
// validate that two vars of the same name which reference the same concrete
|
||||||
// value do not produce a conflict.
|
// value do not produce a conflict.
|
||||||
err := ac0.MergeAccumulator(ac1)
|
err = ac0.MergeAccumulator(ac1)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("see bug gh-1600")
|
t.Fatalf("see bug gh-1600")
|
||||||
}
|
}
|
||||||
@@ -246,10 +253,13 @@ func TestResolveVarConflicts(t *testing.T) {
|
|||||||
// two above (because it contains a variable whose name is used in the other
|
// two above (because it contains a variable whose name is used in the other
|
||||||
// accumulators AND whose concrete values are different).
|
// accumulators AND whose concrete values are different).
|
||||||
rm2 := resmap.New()
|
rm2 := resmap.New()
|
||||||
rm2.Append(rf.FromMap(barGcp))
|
err = rm2.Append(rf.FromMap(barGcp))
|
||||||
|
require.NoError(t, err)
|
||||||
ac2 := MakeEmptyAccumulator()
|
ac2 := MakeEmptyAccumulator()
|
||||||
ac2.AppendAll(rm2)
|
err = ac2.AppendAll(rm2)
|
||||||
ac2.MergeVars([]types.Var{varBar})
|
require.NoError(t, err)
|
||||||
|
err = ac2.MergeVars([]types.Var{varBar})
|
||||||
|
require.NoError(t, err)
|
||||||
err = ac1.MergeAccumulator(ac2)
|
err = ac1.MergeAccumulator(ac2)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("dupe vars w/ different concrete values should conflict")
|
t.Fatalf("dupe vars w/ different concrete values should conflict")
|
||||||
@@ -352,10 +362,10 @@ func TestResolveVarsWithNoambiguation(t *testing.T) {
|
|||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"name": "sub-backendOne",
|
"name": "sub-backendOne",
|
||||||
"annotations": map[string]interface{}{
|
"annotations": map[string]interface{}{
|
||||||
"config.kubernetes.io/previousKinds": "Service",
|
"internal.config.kubernetes.io/previousKinds": "Service",
|
||||||
"config.kubernetes.io/previousNames": "backendOne",
|
"internal.config.kubernetes.io/previousNames": "backendOne",
|
||||||
"config.kubernetes.io/previousNamespaces": "default",
|
"internal.config.kubernetes.io/previousNamespaces": "default",
|
||||||
"config.kubernetes.io/prefixes": "sub-",
|
"internal.config.kubernetes.io/prefixes": "sub-",
|
||||||
},
|
},
|
||||||
}}).ResMap()
|
}}).ResMap()
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,13 @@ func MakeConfigMap(
|
|||||||
if err = rn.LoadMapIntoConfigMapData(m); err != nil {
|
if err = rn.LoadMapIntoConfigMapData(m); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
copyLabelsAndAnnotations(rn, args.Options)
|
err = copyLabelsAndAnnotations(rn, args.Options)
|
||||||
setImmutable(rn, args.Options)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = setImmutable(rn, args.Options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return rn, nil
|
return rn, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
. "sigs.k8s.io/kustomize/api/internal/generators"
|
. "sigs.k8s.io/kustomize/api/internal/generators"
|
||||||
"sigs.k8s.io/kustomize/api/kv"
|
"sigs.k8s.io/kustomize/api/kv"
|
||||||
"sigs.k8s.io/kustomize/api/loader"
|
"sigs.k8s.io/kustomize/api/loader"
|
||||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
var binaryHello = []byte{
|
var binaryHello = []byte{
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
. "sigs.k8s.io/kustomize/api/internal/generators"
|
. "sigs.k8s.io/kustomize/api/internal/generators"
|
||||||
"sigs.k8s.io/kustomize/api/kv"
|
"sigs.k8s.io/kustomize/api/kv"
|
||||||
"sigs.k8s.io/kustomize/api/loader"
|
"sigs.k8s.io/kustomize/api/loader"
|
||||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMakeSecret(t *testing.T) {
|
func TestMakeSecret(t *testing.T) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cloner is a function that can clone a git repo.
|
// Cloner is a function that can clone a git repo.
|
||||||
@@ -14,7 +14,7 @@ type Cloner func(repoSpec *RepoSpec) error
|
|||||||
// to say, some remote API, to obtain a local clone of
|
// to say, some remote API, to obtain a local clone of
|
||||||
// a remote repo.
|
// a remote repo.
|
||||||
func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
||||||
r, err := newCmdRunner()
|
r, err := newCmdRunner(repoSpec.Timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,10 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
|||||||
if err = r.run("checkout", "FETCH_HEAD"); err != nil {
|
if err = r.run("checkout", "FETCH_HEAD"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return r.run("submodule", "update", "--init", "--recursive")
|
if repoSpec.Submodules {
|
||||||
|
return r.run("submodule", "update", "--init", "--recursive")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoNothingCloner returns a cloner that only sets
|
// DoNothingCloner returns a cloner that only sets
|
||||||
|
|||||||
@@ -8,13 +8,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/internal/utils"
|
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Arbitrary, but non-infinite, timeout for running commands.
|
|
||||||
const defaultDuration = 27 * time.Second
|
|
||||||
|
|
||||||
// gitRunner runs the external git binary.
|
// gitRunner runs the external git binary.
|
||||||
type gitRunner struct {
|
type gitRunner struct {
|
||||||
gitProgram string
|
gitProgram string
|
||||||
@@ -24,7 +21,7 @@ type gitRunner struct {
|
|||||||
|
|
||||||
// newCmdRunner returns a gitRunner if it can find the binary.
|
// newCmdRunner returns a gitRunner if it can find the binary.
|
||||||
// It also creats a temp directory for cloning repos.
|
// It also creats a temp directory for cloning repos.
|
||||||
func newCmdRunner() (*gitRunner, error) {
|
func newCmdRunner(timeout time.Duration) (*gitRunner, error) {
|
||||||
gitProgram, err := exec.LookPath("git")
|
gitProgram, err := exec.LookPath("git")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "no 'git' program on path")
|
return nil, errors.Wrap(err, "no 'git' program on path")
|
||||||
@@ -35,7 +32,7 @@ func newCmdRunner() (*gitRunner, error) {
|
|||||||
}
|
}
|
||||||
return &gitRunner{
|
return &gitRunner{
|
||||||
gitProgram: gitProgram,
|
gitProgram: gitProgram,
|
||||||
duration: defaultDuration,
|
duration: timeout,
|
||||||
dir: dir,
|
dir: dir,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ package git
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Used as a temporary non-empty occupant of the cloneDir
|
// Used as a temporary non-empty occupant of the cloneDir
|
||||||
@@ -44,6 +46,12 @@ type RepoSpec struct {
|
|||||||
|
|
||||||
// e.g. .git or empty in case of _git is present
|
// e.g. .git or empty in case of _git is present
|
||||||
GitSuffix string
|
GitSuffix string
|
||||||
|
|
||||||
|
// Submodules indicates whether or not to clone git submodules.
|
||||||
|
Submodules bool
|
||||||
|
|
||||||
|
// Timeout is the maximum duration allowed for execing git commands.
|
||||||
|
Timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloneSpec returns a string suitable for "git clone {spec}".
|
// CloneSpec returns a string suitable for "git clone {spec}".
|
||||||
@@ -70,6 +78,7 @@ func (x *RepoSpec) Cleaner(fSys filesys.FileSystem) func() error {
|
|||||||
return func() error { return fSys.RemoveAll(x.Dir.String()) }
|
return func() error { return fSys.RemoveAll(x.Dir.String()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRepoSpecFromUrl parses git-like urls.
|
||||||
// From strings like git@github.com:someOrg/someRepo.git or
|
// From strings like git@github.com:someOrg/someRepo.git or
|
||||||
// https://github.com/someOrg/someRepo?ref=someHash, extract
|
// https://github.com/someOrg/someRepo?ref=someHash, extract
|
||||||
// the parts.
|
// the parts.
|
||||||
@@ -77,7 +86,7 @@ func NewRepoSpecFromUrl(n string) (*RepoSpec, error) {
|
|||||||
if filepath.IsAbs(n) {
|
if filepath.IsAbs(n) {
|
||||||
return nil, fmt.Errorf("uri looks like abs path: %s", n)
|
return nil, fmt.Errorf("uri looks like abs path: %s", n)
|
||||||
}
|
}
|
||||||
host, orgRepo, path, gitRef, gitSuffix := parseGitUrl(n)
|
host, orgRepo, path, gitRef, gitSubmodules, suffix, gitTimeout := parseGitUrl(n)
|
||||||
if orgRepo == "" {
|
if orgRepo == "" {
|
||||||
return nil, fmt.Errorf("url lacks orgRepo: %s", n)
|
return nil, fmt.Errorf("url lacks orgRepo: %s", n)
|
||||||
}
|
}
|
||||||
@@ -86,28 +95,28 @@ func NewRepoSpecFromUrl(n string) (*RepoSpec, error) {
|
|||||||
}
|
}
|
||||||
return &RepoSpec{
|
return &RepoSpec{
|
||||||
raw: n, Host: host, OrgRepo: orgRepo,
|
raw: n, Host: host, OrgRepo: orgRepo,
|
||||||
Dir: notCloned, Path: path, Ref: gitRef, GitSuffix: gitSuffix}, nil
|
Dir: notCloned, Path: path, Ref: gitRef, GitSuffix: suffix,
|
||||||
|
Submodules: gitSubmodules, Timeout: gitTimeout}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
refQuery = "?ref="
|
refQuery = "?ref="
|
||||||
refQueryRegex = "\\?(version|ref)="
|
gitSuffix = ".git"
|
||||||
gitSuffix = ".git"
|
gitDelimiter = "_git/"
|
||||||
gitDelimiter = "_git/"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// From strings like git@github.com:someOrg/someRepo.git or
|
// From strings like git@github.com:someOrg/someRepo.git or
|
||||||
// https://github.com/someOrg/someRepo?ref=someHash, extract
|
// https://github.com/someOrg/someRepo?ref=someHash, extract
|
||||||
// the parts.
|
// the parts.
|
||||||
func parseGitUrl(n string) (
|
func parseGitUrl(n string) (
|
||||||
host string, orgRepo string, path string, gitRef string, gitSuff string) {
|
host string, orgRepo string, path string, gitRef string, gitSubmodules bool, gitSuff string, gitTimeout time.Duration) {
|
||||||
|
|
||||||
if strings.Contains(n, gitDelimiter) {
|
if strings.Contains(n, gitDelimiter) {
|
||||||
index := strings.Index(n, gitDelimiter)
|
index := strings.Index(n, gitDelimiter)
|
||||||
// Adding _git/ to host
|
// Adding _git/ to host
|
||||||
host = normalizeGitHostSpec(n[:index+len(gitDelimiter)])
|
host = normalizeGitHostSpec(n[:index+len(gitDelimiter)])
|
||||||
orgRepo = strings.Split(strings.Split(n[index+len(gitDelimiter):], "/")[0], "?")[0]
|
orgRepo = strings.Split(strings.Split(n[index+len(gitDelimiter):], "/")[0], "?")[0]
|
||||||
path, gitRef = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):])
|
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n[index+len(gitDelimiter)+len(orgRepo):])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
host, n = parseHostSpec(n)
|
host, n = parseHostSpec(n)
|
||||||
@@ -116,35 +125,75 @@ func parseGitUrl(n string) (
|
|||||||
index := strings.Index(n, gitSuffix)
|
index := strings.Index(n, gitSuffix)
|
||||||
orgRepo = n[0:index]
|
orgRepo = n[0:index]
|
||||||
n = n[index+len(gitSuffix):]
|
n = n[index+len(gitSuffix):]
|
||||||
path, gitRef = peelQuery(n)
|
if len(n) > 0 && n[0] == '/' {
|
||||||
|
n = n[1:]
|
||||||
|
}
|
||||||
|
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
i := strings.Index(n, "/")
|
i := strings.Index(n, "/")
|
||||||
if i < 1 {
|
if i < 1 {
|
||||||
return "", "", "", "", ""
|
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
j := strings.Index(n[i+1:], "/")
|
j := strings.Index(n[i+1:], "/")
|
||||||
if j >= 0 {
|
if j >= 0 {
|
||||||
j += i + 1
|
j += i + 1
|
||||||
orgRepo = n[:j]
|
orgRepo = n[:j]
|
||||||
path, gitRef = peelQuery(n[j+1:])
|
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n[j+1:])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
path = ""
|
path = ""
|
||||||
orgRepo, gitRef = peelQuery(n)
|
orgRepo, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
|
||||||
return host, orgRepo, path, gitRef, gitSuff
|
return host, orgRepo, path, gitRef, gitSubmodules, gitSuff, gitTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
func peelQuery(arg string) (string, string) {
|
// Clone git submodules by default.
|
||||||
|
const defaultSubmodules = true
|
||||||
|
|
||||||
r, _ := regexp.Compile(refQueryRegex)
|
// Arbitrary, but non-infinite, timeout for running commands.
|
||||||
j := r.FindStringIndex(arg)
|
const defaultTimeout = 27 * time.Second
|
||||||
|
|
||||||
if len(j) > 0 {
|
func peelQuery(arg string) (string, string, time.Duration, bool) {
|
||||||
return arg[:j[0]], arg[j[0]+len(r.FindString(arg)):]
|
// Parse the given arg into a URL. In the event of a parse failure, return
|
||||||
|
// our defaults.
|
||||||
|
parsed, err := url.Parse(arg)
|
||||||
|
if err != nil {
|
||||||
|
return arg, "", defaultTimeout, defaultSubmodules
|
||||||
}
|
}
|
||||||
return arg, ""
|
values := parsed.Query()
|
||||||
|
|
||||||
|
// ref is the desired git ref to target. Can be specified by in a git URL
|
||||||
|
// with ?ref=<string> or ?version=<string>, although ref takes precedence.
|
||||||
|
ref := values.Get("version")
|
||||||
|
if queryValue := values.Get("ref"); queryValue != "" {
|
||||||
|
ref = queryValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// depth is the desired git exec timeout. Can be specified by in a git URL
|
||||||
|
// with ?timeout=<duration>.
|
||||||
|
duration := defaultTimeout
|
||||||
|
if queryValue := values.Get("timeout"); queryValue != "" {
|
||||||
|
// Attempt to first parse as a number of integer seconds (like "61"),
|
||||||
|
// and then attempt to parse as a suffixed duration (like "61s").
|
||||||
|
if intValue, err := strconv.Atoi(queryValue); err == nil && intValue > 0 {
|
||||||
|
duration = time.Duration(intValue) * time.Second
|
||||||
|
} else if durationValue, err := time.ParseDuration(queryValue); err == nil && durationValue > 0 {
|
||||||
|
duration = durationValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// submodules indicates if git submodule cloning is desired. Can be
|
||||||
|
// specified by in a git URL with ?submodules=<bool>.
|
||||||
|
submodules := defaultSubmodules
|
||||||
|
if queryValue := values.Get("submodules"); queryValue != "" {
|
||||||
|
if boolValue, err := strconv.ParseBool(queryValue); err == nil {
|
||||||
|
submodules = boolValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed.Path, ref, duration, submodules
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseHostSpec(n string) (string, string) {
|
func parseHostSpec(n string) (string, string) {
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var orgRepos = []string{"someOrg/someRepo", "kubernetes/website"}
|
var orgRepos = []string{"someOrg/someRepo", "kubernetes/website"}
|
||||||
@@ -32,7 +35,6 @@ var hostNamesRawAndNormalized = [][]string{
|
|||||||
{"git::https://git.example.com/", "https://git.example.com/"},
|
{"git::https://git.example.com/", "https://git.example.com/"},
|
||||||
{"git@github.com:", "git@github.com:"},
|
{"git@github.com:", "git@github.com:"},
|
||||||
{"git@github.com/", "git@github.com:"},
|
{"git@github.com/", "git@github.com:"},
|
||||||
{"git@gitlab2.sqtools.ru:10022/", "git@gitlab2.sqtools.ru:10022/"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeUrl(hostFmt, orgRepo, path, href string) string {
|
func makeUrl(hostFmt, orgRepo, path, href string) string {
|
||||||
@@ -108,96 +110,93 @@ func TestNewRepoSpecFromUrlErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNewRepoSpecFromUrl_CloneSpecs(t *testing.T) {
|
func TestNewRepoSpecFromUrl_CloneSpecs(t *testing.T) {
|
||||||
testcases := []struct {
|
testcases := map[string]struct {
|
||||||
input string
|
input string
|
||||||
cloneSpec string
|
cloneSpec string
|
||||||
absPath string
|
absPath string
|
||||||
ref string
|
ref string
|
||||||
}{
|
}{
|
||||||
{
|
"t1": {
|
||||||
input: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo/somedir",
|
input: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo/somedir",
|
||||||
cloneSpec: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo",
|
cloneSpec: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo",
|
||||||
absPath: notCloned.Join("somedir"),
|
absPath: notCloned.Join("somedir"),
|
||||||
ref: "",
|
ref: "",
|
||||||
},
|
},
|
||||||
{
|
"t2": {
|
||||||
input: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo/somedir?ref=testbranch",
|
input: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo/somedir?ref=testbranch",
|
||||||
cloneSpec: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo",
|
cloneSpec: "https://git-codecommit.us-east-2.amazonaws.com/someorg/somerepo",
|
||||||
absPath: notCloned.Join("somedir"),
|
absPath: notCloned.Join("somedir"),
|
||||||
ref: "testbranch",
|
ref: "testbranch",
|
||||||
},
|
},
|
||||||
{
|
"t3": {
|
||||||
input: "https://fabrikops2.visualstudio.com/someorg/somerepo?ref=master",
|
input: "https://fabrikops2.visualstudio.com/someorg/somerepo?ref=master",
|
||||||
cloneSpec: "https://fabrikops2.visualstudio.com/someorg/somerepo",
|
cloneSpec: "https://fabrikops2.visualstudio.com/someorg/somerepo",
|
||||||
absPath: notCloned.String(),
|
absPath: notCloned.String(),
|
||||||
ref: "master",
|
ref: "master",
|
||||||
},
|
},
|
||||||
{
|
"t4": {
|
||||||
input: "http://github.com/someorg/somerepo/somedir",
|
input: "http://github.com/someorg/somerepo/somedir",
|
||||||
cloneSpec: "https://github.com/someorg/somerepo.git",
|
cloneSpec: "https://github.com/someorg/somerepo.git",
|
||||||
absPath: notCloned.Join("somedir"),
|
absPath: notCloned.Join("somedir"),
|
||||||
ref: "",
|
ref: "",
|
||||||
},
|
},
|
||||||
{
|
"t5": {
|
||||||
input: "git@github.com:someorg/somerepo/somedir",
|
input: "git@github.com:someorg/somerepo/somedir",
|
||||||
cloneSpec: "git@github.com:someorg/somerepo.git",
|
cloneSpec: "git@github.com:someorg/somerepo.git",
|
||||||
absPath: notCloned.Join("somedir"),
|
absPath: notCloned.Join("somedir"),
|
||||||
ref: "",
|
ref: "",
|
||||||
},
|
},
|
||||||
{
|
"t6": {
|
||||||
input: "git@gitlab2.sqtools.ru:10022/infra/kubernetes/thanos-base.git?ref=v0.1.0",
|
input: "git@gitlab2.sqtools.ru:10022/infra/kubernetes/thanos-base.git?ref=v0.1.0",
|
||||||
cloneSpec: "git@gitlab2.sqtools.ru:10022/infra/kubernetes/thanos-base.git",
|
cloneSpec: "git@gitlab2.sqtools.ru:10022/infra/kubernetes/thanos-base.git",
|
||||||
absPath: notCloned.String(),
|
absPath: notCloned.String(),
|
||||||
ref: "v0.1.0",
|
ref: "v0.1.0",
|
||||||
},
|
},
|
||||||
{
|
"t7": {
|
||||||
input: "git@bitbucket.org:company/project.git//path?ref=branch",
|
input: "git@bitbucket.org:company/project.git//path?ref=branch",
|
||||||
cloneSpec: "git@bitbucket.org:company/project.git",
|
cloneSpec: "git@bitbucket.org:company/project.git",
|
||||||
absPath: notCloned.Join("path"),
|
absPath: notCloned.Join("path"),
|
||||||
ref: "branch",
|
ref: "branch",
|
||||||
},
|
},
|
||||||
{
|
"t8": {
|
||||||
input: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
input: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
||||||
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
||||||
absPath: notCloned.String(),
|
absPath: notCloned.String(),
|
||||||
ref: "",
|
ref: "",
|
||||||
},
|
},
|
||||||
{
|
"t9": {
|
||||||
input: "https://itfs.mycompany.com/collection/project/_git/somerepos?version=v1.0.0",
|
input: "https://itfs.mycompany.com/collection/project/_git/somerepos?version=v1.0.0",
|
||||||
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
||||||
absPath: notCloned.String(),
|
absPath: notCloned.String(),
|
||||||
ref: "v1.0.0",
|
ref: "v1.0.0",
|
||||||
},
|
},
|
||||||
{
|
"t10": {
|
||||||
input: "https://itfs.mycompany.com/collection/project/_git/somerepos/somedir?version=v1.0.0",
|
input: "https://itfs.mycompany.com/collection/project/_git/somerepos/somedir?version=v1.0.0",
|
||||||
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
||||||
absPath: notCloned.Join("somedir"),
|
absPath: notCloned.Join("somedir"),
|
||||||
ref: "v1.0.0",
|
ref: "v1.0.0",
|
||||||
},
|
},
|
||||||
{
|
"t11": {
|
||||||
input: "git::https://itfs.mycompany.com/collection/project/_git/somerepos",
|
input: "git::https://itfs.mycompany.com/collection/project/_git/somerepos",
|
||||||
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
cloneSpec: "https://itfs.mycompany.com/collection/project/_git/somerepos",
|
||||||
absPath: notCloned.String(),
|
absPath: notCloned.String(),
|
||||||
ref: "",
|
ref: "",
|
||||||
},
|
},
|
||||||
|
"t12": {
|
||||||
|
input: "https://bitbucket.example.com/scm/project/repository.git",
|
||||||
|
cloneSpec: "https://bitbucket.example.com/scm/project/repository.git",
|
||||||
|
absPath: notCloned.String(),
|
||||||
|
ref: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, testcase := range testcases {
|
for tn, tc := range testcases {
|
||||||
rs, err := NewRepoSpecFromUrl(testcase.input)
|
t.Run(tn, func(t *testing.T) {
|
||||||
if err != nil {
|
rs, err := NewRepoSpecFromUrl(tc.input)
|
||||||
t.Errorf("Unexpected error: %v", err)
|
assert.NoError(t, err)
|
||||||
}
|
assert.Equal(t, tc.cloneSpec, rs.CloneSpec(), "cloneSpec mismatch")
|
||||||
if rs.CloneSpec() != testcase.cloneSpec {
|
assert.Equal(t, tc.absPath, rs.AbsPath(), "absPath mismatch")
|
||||||
t.Errorf("CloneSpec expected to be %v, but got %v on %s",
|
assert.Equal(t, tc.ref, rs.Ref, "ref mismatch")
|
||||||
testcase.cloneSpec, rs.CloneSpec(), testcase.input)
|
})
|
||||||
}
|
|
||||||
if rs.AbsPath() != testcase.absPath {
|
|
||||||
t.Errorf("AbsPath expected to be %v, but got %v on %s",
|
|
||||||
testcase.absPath, rs.AbsPath(), testcase.input)
|
|
||||||
}
|
|
||||||
if rs.Ref != testcase.ref {
|
|
||||||
t.Errorf("ref expected to be %v, but got %v on %s",
|
|
||||||
testcase.ref, rs.Ref, testcase.input)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,28 +231,134 @@ func TestIsAzureHost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPeelQuery(t *testing.T) {
|
func TestPeelQuery(t *testing.T) {
|
||||||
testcases := []struct {
|
testcases := map[string]struct {
|
||||||
input string
|
input string
|
||||||
expect [2]string
|
path string
|
||||||
|
ref string
|
||||||
|
submodules bool
|
||||||
|
timeout time.Duration
|
||||||
}{
|
}{
|
||||||
{
|
"t1": {
|
||||||
input: "somerepos?ref=v1.0.0",
|
// All empty.
|
||||||
expect: [2]string{"somerepos", "v1.0.0"},
|
input: "somerepos",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
},
|
},
|
||||||
{
|
"t2": {
|
||||||
input: "somerepos?version=master",
|
input: "somerepos?ref=v1.0.0",
|
||||||
expect: [2]string{"somerepos", "master"},
|
path: "somerepos",
|
||||||
|
ref: "v1.0.0",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
},
|
},
|
||||||
{
|
"t3": {
|
||||||
input: "somerepos",
|
input: "somerepos?version=master",
|
||||||
expect: [2]string{"somerepos", ""},
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t4": {
|
||||||
|
// A ref value takes precedence over a version value.
|
||||||
|
input: "somerepos?version=master&ref=v1.0.0",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "v1.0.0",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t5": {
|
||||||
|
// Empty submodules value uses default.
|
||||||
|
input: "somerepos?version=master&submodules=",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t6": {
|
||||||
|
// Malformed submodules value uses default.
|
||||||
|
input: "somerepos?version=master&submodules=maybe",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t7": {
|
||||||
|
input: "somerepos?version=master&submodules=true",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: true,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t8": {
|
||||||
|
input: "somerepos?version=master&submodules=false",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: false,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t9": {
|
||||||
|
// Empty timeout value uses default.
|
||||||
|
input: "somerepos?version=master&timeout=",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t10": {
|
||||||
|
// Malformed timeout value uses default.
|
||||||
|
input: "somerepos?version=master&timeout=jiffy",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t11": {
|
||||||
|
// Zero timeout value uses default.
|
||||||
|
input: "somerepos?version=master&timeout=0",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t12": {
|
||||||
|
input: "somerepos?version=master&timeout=0s",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: defaultTimeout,
|
||||||
|
},
|
||||||
|
"t13": {
|
||||||
|
input: "somerepos?version=master&timeout=61",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: 61 * time.Second,
|
||||||
|
},
|
||||||
|
"t14": {
|
||||||
|
input: "somerepos?version=master&timeout=1m1s",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: defaultSubmodules,
|
||||||
|
timeout: 61 * time.Second,
|
||||||
|
},
|
||||||
|
"t15": {
|
||||||
|
input: "somerepos?version=master&submodules=false&timeout=1m1s",
|
||||||
|
path: "somerepos",
|
||||||
|
ref: "master",
|
||||||
|
submodules: false,
|
||||||
|
timeout: 61 * time.Second,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, testcase := range testcases {
|
for tn, tc := range testcases {
|
||||||
path, ref := peelQuery(testcase.input)
|
t.Run(tn, func(t *testing.T) {
|
||||||
if path != testcase.expect[0] || ref != testcase.expect[1] {
|
path, ref, timeout, submodules := peelQuery(tc.input)
|
||||||
t.Errorf("peelQuery: expected (%s, %s) got (%s, %s) on %s", testcase.expect[0], testcase.expect[1], path, ref, testcase.input)
|
assert.Equal(t, tc.path, path, "path mismatch")
|
||||||
}
|
assert.Equal(t, tc.ref, ref, "ref mismatch")
|
||||||
|
assert.Equal(t, tc.timeout, timeout, "timeout mismatch")
|
||||||
|
assert.Equal(t, tc.submodules, submodules, "submodules mismatch")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/loader"
|
"sigs.k8s.io/kustomize/api/loader"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoadDefaultConfigsFromFiles(t *testing.T) {
|
func TestLoadDefaultConfigsFromFiles(t *testing.T) {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ package builtinconfig
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NameBackReferences is an association between a gvk.GVK (a ReferralTarget)
|
// NameBackReferences is an association between a gvk.GVK (a ReferralTarget)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMergeAll(t *testing.T) {
|
func TestMergeAll(t *testing.T) {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
. "sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMakeDefaultConfig(t *testing.T) {
|
func TestMakeDefaultConfig(t *testing.T) {
|
||||||
|
|||||||
@@ -11,25 +11,26 @@ func _() {
|
|||||||
_ = x[Unknown-0]
|
_ = x[Unknown-0]
|
||||||
_ = x[AnnotationsTransformer-1]
|
_ = x[AnnotationsTransformer-1]
|
||||||
_ = x[ConfigMapGenerator-2]
|
_ = x[ConfigMapGenerator-2]
|
||||||
_ = x[HashTransformer-3]
|
_ = x[IAMPolicyGenerator-3]
|
||||||
_ = x[ImageTagTransformer-4]
|
_ = x[HashTransformer-4]
|
||||||
_ = x[LabelTransformer-5]
|
_ = x[ImageTagTransformer-5]
|
||||||
_ = x[LegacyOrderTransformer-6]
|
_ = x[LabelTransformer-6]
|
||||||
_ = x[NamespaceTransformer-7]
|
_ = x[LegacyOrderTransformer-7]
|
||||||
_ = x[PatchJson6902Transformer-8]
|
_ = x[NamespaceTransformer-8]
|
||||||
_ = x[PatchStrategicMergeTransformer-9]
|
_ = x[PatchJson6902Transformer-9]
|
||||||
_ = x[PatchTransformer-10]
|
_ = x[PatchStrategicMergeTransformer-10]
|
||||||
_ = x[PrefixSuffixTransformer-11]
|
_ = x[PatchTransformer-11]
|
||||||
_ = x[ReplicaCountTransformer-12]
|
_ = x[PrefixSuffixTransformer-12]
|
||||||
_ = x[SecretGenerator-13]
|
_ = x[ReplicaCountTransformer-13]
|
||||||
_ = x[ValueAddTransformer-14]
|
_ = x[SecretGenerator-14]
|
||||||
_ = x[HelmChartInflationGenerator-15]
|
_ = x[ValueAddTransformer-15]
|
||||||
_ = x[ReplacementTransformer-16]
|
_ = x[HelmChartInflationGenerator-16]
|
||||||
|
_ = x[ReplacementTransformer-17]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGeneratorReplacementTransformer"
|
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorIAMPolicyGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGeneratorReplacementTransformer"
|
||||||
|
|
||||||
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 97, 119, 139, 163, 193, 209, 232, 255, 270, 289, 316, 338}
|
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 65, 80, 99, 115, 137, 157, 181, 211, 227, 250, 273, 288, 307, 334, 356}
|
||||||
|
|
||||||
func (i BuiltinPluginType) String() string {
|
func (i BuiltinPluginType) String() string {
|
||||||
if i < 0 || i >= BuiltinPluginType(len(_BuiltinPluginType_index)-1) {
|
if i < 0 || i >= BuiltinPluginType(len(_BuiltinPluginType_index)-1) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ const (
|
|||||||
Unknown BuiltinPluginType = iota
|
Unknown BuiltinPluginType = iota
|
||||||
AnnotationsTransformer
|
AnnotationsTransformer
|
||||||
ConfigMapGenerator
|
ConfigMapGenerator
|
||||||
|
IAMPolicyGenerator
|
||||||
HashTransformer
|
HashTransformer
|
||||||
ImageTagTransformer
|
ImageTagTransformer
|
||||||
LabelTransformer
|
LabelTransformer
|
||||||
@@ -58,6 +59,7 @@ func GetBuiltinPluginType(n string) BuiltinPluginType {
|
|||||||
|
|
||||||
var GeneratorFactories = map[BuiltinPluginType]func() resmap.GeneratorPlugin{
|
var GeneratorFactories = map[BuiltinPluginType]func() resmap.GeneratorPlugin{
|
||||||
ConfigMapGenerator: builtins.NewConfigMapGeneratorPlugin,
|
ConfigMapGenerator: builtins.NewConfigMapGeneratorPlugin,
|
||||||
|
IAMPolicyGenerator: builtins.NewIAMPolicyGeneratorPlugin,
|
||||||
SecretGenerator: builtins.NewSecretGeneratorPlugin,
|
SecretGenerator: builtins.NewSecretGeneratorPlugin,
|
||||||
HelmChartInflationGenerator: builtins.NewHelmChartInflationGeneratorPlugin,
|
HelmChartInflationGenerator: builtins.NewHelmChartInflationGeneratorPlugin,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
. "sigs.k8s.io/kustomize/api/internal/plugins/compiler"
|
. "sigs.k8s.io/kustomize/api/internal/plugins/compiler"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Regression coverage over compiler behavior.
|
// Regression coverage over compiler behavior.
|
||||||
|
|||||||
@@ -94,9 +94,6 @@ TO GENERATE CODE
|
|||||||
cd $repo/plugin/builtin
|
cd $repo/plugin/builtin
|
||||||
go generate ./...
|
go generate ./...
|
||||||
|
|
||||||
See scripts/kyaml-pre-commit.sh for canonical way
|
|
||||||
to execute the above.
|
|
||||||
|
|
||||||
This creates
|
This creates
|
||||||
|
|
||||||
$repo/api/plugins/builtins/SecretGenerator.go
|
$repo/api/plugins/builtins/SecretGenerator.go
|
||||||
|
|||||||
@@ -89,7 +89,10 @@ type argsConfig struct {
|
|||||||
|
|
||||||
func (p *ExecPlugin) processOptionalArgsFields() error {
|
func (p *ExecPlugin) processOptionalArgsFields() error {
|
||||||
var c argsConfig
|
var c argsConfig
|
||||||
yaml.Unmarshal(p.cfg, &c)
|
err := yaml.Unmarshal(p.cfg, &c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if c.ArgsOneLiner != "" {
|
if c.ArgsOneLiner != "" {
|
||||||
p.args, _ = shlex.Split(c.ArgsOneLiner)
|
p.args, _ = shlex.Split(c.ArgsOneLiner)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"github.com/stretchr/testify/require"
|
||||||
. "sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
. "sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
||||||
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
||||||
@@ -17,15 +17,17 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/provider"
|
"sigs.k8s.io/kustomize/api/provider"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExecPluginConfig(t *testing.T) {
|
func TestExecPluginConfig(t *testing.T) {
|
||||||
fSys := filesys.MakeFsInMemory()
|
fSys := filesys.MakeFsInMemory()
|
||||||
fSys.WriteFile("sed-input.txt", []byte(`
|
err := fSys.WriteFile("sed-input.txt", []byte(`
|
||||||
s/$FOO/foo/g
|
s/$FOO/foo/g
|
||||||
s/$BAR/bar baz/g
|
s/$BAR/bar baz/g
|
||||||
\ \ \
|
\ \ \
|
||||||
`))
|
`))
|
||||||
|
require.NoError(t, err)
|
||||||
ldr, err := fLdr.NewLoader(
|
ldr, err := fLdr.NewLoader(
|
||||||
fLdr.RestrictionRootOnly, filesys.Separator, fSys)
|
fLdr.RestrictionRootOnly, filesys.Separator, fSys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -62,9 +64,10 @@ s/$BAR/bar baz/g
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
}
|
}
|
||||||
p.Config(
|
err = p.Config(
|
||||||
resmap.NewPluginHelpers(ldr, pvd.GetFieldValidator(), rf, pc),
|
resmap.NewPluginHelpers(ldr, pvd.GetFieldValidator(), rf, pc),
|
||||||
yaml)
|
yaml)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
expected := "someteam.example.com/v1/sedtransformer/SedTransformer"
|
expected := "someteam.example.com/v1/sedtransformer/SedTransformer"
|
||||||
if !strings.HasSuffix(p.Path(), expected) {
|
if !strings.HasSuffix(p.Path(), expected) {
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ func NewFnPlugin(o *types.FnPluginLoadingOptions) *FnPlugin {
|
|||||||
EnableExec: o.EnableExec,
|
EnableExec: o.EnableExec,
|
||||||
StorageMounts: toStorageMounts(o.Mounts),
|
StorageMounts: toStorageMounts(o.Mounts),
|
||||||
Env: o.Env,
|
Env: o.Env,
|
||||||
|
AsCurrentUser: o.AsCurrentUser,
|
||||||
|
WorkingDir: o.WorkingDir,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,17 +13,17 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
"sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/fnplugin"
|
"sigs.k8s.io/kustomize/api/internal/plugins/fnplugin"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Loader loads plugins using a file loader (a different loader).
|
// Loader loads plugins using a file loader (a different loader).
|
||||||
@@ -47,6 +47,11 @@ func (l *Loader) Config() *types.PluginConfig {
|
|||||||
return l.pc
|
return l.pc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetWorkDir sets the working directory for this loader's plugins
|
||||||
|
func (l *Loader) SetWorkDir(wd string) {
|
||||||
|
l.pc.FnpLoadingOptions.WorkingDir = wd
|
||||||
|
}
|
||||||
|
|
||||||
func (l *Loader) LoadGenerators(
|
func (l *Loader) LoadGenerators(
|
||||||
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) ([]resmap.Generator, error) {
|
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) ([]resmap.Generator, error) {
|
||||||
var result []resmap.Generator
|
var result []resmap.Generator
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ package loader_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
. "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
. "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||||
"sigs.k8s.io/kustomize/api/loader"
|
"sigs.k8s.io/kustomize/api/loader"
|
||||||
"sigs.k8s.io/kustomize/api/provider"
|
"sigs.k8s.io/kustomize/api/provider"
|
||||||
@@ -14,6 +13,7 @@ import (
|
|||||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -137,7 +137,9 @@ func GetResMapWithIDAnnotation(rm resmap.ResMap) (resmap.ResMap, error) {
|
|||||||
}
|
}
|
||||||
annotations := r.GetAnnotations()
|
annotations := r.GetAnnotations()
|
||||||
annotations[idAnnotation] = string(idString)
|
annotations[idAnnotation] = string(idString)
|
||||||
r.SetAnnotations(annotations)
|
if err = r.SetAnnotations(annotations); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return inputRM, nil
|
return inputRM, nil
|
||||||
}
|
}
|
||||||
@@ -158,7 +160,10 @@ func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byt
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range resources {
|
for _, r := range resources {
|
||||||
removeIDAnnotation(r) // stale--not manipulated by plugin transformers
|
// stale--not manipulated by plugin transformers
|
||||||
|
if err = removeIDAnnotation(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Add to the new map, checking for duplicates
|
// Add to the new map, checking for duplicates
|
||||||
if err := newMap.Append(r); err != nil {
|
if err := newMap.Append(r); err != nil {
|
||||||
@@ -175,7 +180,7 @@ func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byt
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if oldIdx != -1 {
|
if oldIdx != -1 {
|
||||||
rm.GetByIndex(oldIdx).ResetPrimaryData(r)
|
rm.GetByIndex(oldIdx).ResetRNode(r)
|
||||||
} else {
|
} else {
|
||||||
if err := rm.Append(r); err != nil {
|
if err := rm.Append(r); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -187,21 +192,20 @@ func UpdateResMapValues(pluginName string, h *resmap.PluginHelpers, output []byt
|
|||||||
for _, id := range rm.AllIds() {
|
for _, id := range rm.AllIds() {
|
||||||
newIdx, _ := newMap.GetIndexOfCurrentId(id)
|
newIdx, _ := newMap.GetIndexOfCurrentId(id)
|
||||||
if newIdx == -1 {
|
if newIdx == -1 {
|
||||||
rm.Remove(id)
|
if err = rm.Remove(id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeIDAnnotation(r *resource.Resource) {
|
func removeIDAnnotation(r *resource.Resource) error {
|
||||||
// remove the annotation set by Kustomize to track the resource
|
// remove the annotation set by Kustomize to track the resource
|
||||||
annotations := r.GetAnnotations()
|
annotations := r.GetAnnotations()
|
||||||
delete(annotations, idAnnotation)
|
delete(annotations, idAnnotation)
|
||||||
if len(annotations) == 0 {
|
return r.SetAnnotations(annotations)
|
||||||
annotations = nil
|
|
||||||
}
|
|
||||||
r.SetAnnotations(annotations)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateResourceOptions updates the generator options for each resource in the
|
// UpdateResourceOptions updates the generator options for each resource in the
|
||||||
@@ -224,14 +228,13 @@ func UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, error) {
|
|||||||
}
|
}
|
||||||
delete(annotations, HashAnnotation)
|
delete(annotations, HashAnnotation)
|
||||||
delete(annotations, BehaviorAnnotation)
|
delete(annotations, BehaviorAnnotation)
|
||||||
if len(annotations) == 0 {
|
if err := r.SetAnnotations(annotations); err != nil {
|
||||||
annotations = nil
|
return nil, err
|
||||||
}
|
}
|
||||||
r.SetAnnotations(annotations)
|
if needsHash {
|
||||||
r.SetOptions(types.NewGenArgs(
|
r.EnableHashSuffix()
|
||||||
&types.GeneratorArgs{
|
}
|
||||||
Behavior: behavior,
|
r.SetBehavior(types.NewGenerationBehavior(behavior))
|
||||||
Options: &types.GeneratorOptions{DisableNameSuffixHash: !needsHash}}))
|
|
||||||
}
|
}
|
||||||
return rm, nil
|
return rm, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"github.com/stretchr/testify/require"
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/api/provider"
|
"sigs.k8s.io/kustomize/api/provider"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDeterminePluginSrcRoot(t *testing.T) {
|
func TestDeterminePluginSrcRoot(t *testing.T) {
|
||||||
@@ -45,7 +46,9 @@ func makeConfigMap(rf *resource.Factory, name, behavior string, hashValue *strin
|
|||||||
annotations[HashAnnotation] = *hashValue
|
annotations[HashAnnotation] = *hashValue
|
||||||
}
|
}
|
||||||
if len(annotations) > 0 {
|
if len(annotations) > 0 {
|
||||||
r.SetAnnotations(annotations)
|
if err := r.SetAnnotations(annotations); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -84,8 +87,10 @@ func TestUpdateResourceOptions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for i, c := range cases {
|
for i, c := range cases {
|
||||||
name := fmt.Sprintf("test%d", i)
|
name := fmt.Sprintf("test%d", i)
|
||||||
in.Append(makeConfigMap(rf, name, c.behavior, c.hashValue))
|
err := in.Append(makeConfigMap(rf, name, c.behavior, c.hashValue))
|
||||||
expected.Append(makeConfigMapOptions(rf, name, c.behavior, !c.needsHash))
|
require.NoError(t, err)
|
||||||
|
err = expected.Append(makeConfigMapOptions(rf, name, c.behavior, !c.needsHash))
|
||||||
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
actual, err := UpdateResourceOptions(in)
|
actual, err := UpdateResourceOptions(in)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -103,10 +108,9 @@ func TestUpdateResourceOptionsWithInvalidHashAnnotationValues(t *testing.T) {
|
|||||||
for i, c := range cases {
|
for i, c := range cases {
|
||||||
name := fmt.Sprintf("test%d", i)
|
name := fmt.Sprintf("test%d", i)
|
||||||
in := resmap.New()
|
in := resmap.New()
|
||||||
in.Append(makeConfigMap(rf, name, "", &c))
|
err := in.Append(makeConfigMap(rf, name, "", &c))
|
||||||
_, err := UpdateResourceOptions(in)
|
require.NoError(t, err)
|
||||||
if err == nil {
|
_, err = UpdateResourceOptions(in)
|
||||||
t.Errorf("expected error from value %q", c)
|
require.Error(t, err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,10 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||||
"sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
"sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
@@ -38,11 +40,13 @@ func NewKustTarget(
|
|||||||
validator ifc.Validator,
|
validator ifc.Validator,
|
||||||
rFactory *resmap.Factory,
|
rFactory *resmap.Factory,
|
||||||
pLdr *loader.Loader) *KustTarget {
|
pLdr *loader.Loader) *KustTarget {
|
||||||
|
pLdrCopy := *pLdr
|
||||||
|
pLdrCopy.SetWorkDir(ldr.Root())
|
||||||
return &KustTarget{
|
return &KustTarget{
|
||||||
ldr: ldr,
|
ldr: ldr,
|
||||||
validator: validator,
|
validator: validator,
|
||||||
rFactory: rFactory,
|
rFactory: rFactory,
|
||||||
pLdr: pLdr,
|
pLdr: &pLdrCopy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +112,7 @@ func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) makeCustomizedResMap() (resmap.ResMap, error) {
|
func (kt *KustTarget) makeCustomizedResMap() (resmap.ResMap, error) {
|
||||||
ra, err := kt.AccumulateTarget()
|
ra, err := kt.AccumulateTarget(&resource.Origin{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -151,20 +155,29 @@ func (kt *KustTarget) addHashesToNames(
|
|||||||
// holding customized resources and the data/rules used
|
// holding customized resources and the data/rules used
|
||||||
// to do so. The name back references and vars are
|
// to do so. The name back references and vars are
|
||||||
// not yet fixed.
|
// not yet fixed.
|
||||||
func (kt *KustTarget) AccumulateTarget() (
|
// The origin parameter is used through the recursive calls
|
||||||
|
// to annotate each resource with information about where
|
||||||
|
// the resource came from, e.g. the file and/or the repository
|
||||||
|
// it originated from.
|
||||||
|
// As an entrypoint, one can pass an empty resource.Origin object to
|
||||||
|
// AccumulateTarget. As AccumulateTarget moves recursively
|
||||||
|
// through kustomization directories, it updates `origin.path`
|
||||||
|
// accordingly. When a remote base is found, it updates `origin.repo`
|
||||||
|
// and `origin.ref` accordingly.
|
||||||
|
func (kt *KustTarget) AccumulateTarget(origin *resource.Origin) (
|
||||||
ra *accumulator.ResAccumulator, err error) {
|
ra *accumulator.ResAccumulator, err error) {
|
||||||
return kt.accumulateTarget(accumulator.MakeEmptyAccumulator())
|
return kt.accumulateTarget(accumulator.MakeEmptyAccumulator(), origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ra should be empty when this KustTarget is a Kustomization, or the ra of the parent if this KustTarget is a Component
|
// ra should be empty when this KustTarget is a Kustomization, or the ra of the parent if this KustTarget is a Component
|
||||||
// (or empty if the Component does not have a parent).
|
// (or empty if the Component does not have a parent).
|
||||||
func (kt *KustTarget) accumulateTarget(ra *accumulator.ResAccumulator) (
|
func (kt *KustTarget) accumulateTarget(ra *accumulator.ResAccumulator, origin *resource.Origin) (
|
||||||
resRa *accumulator.ResAccumulator, err error) {
|
resRa *accumulator.ResAccumulator, err error) {
|
||||||
ra, err = kt.accumulateResources(ra, kt.kustomization.Resources)
|
ra, err = kt.accumulateResources(ra, kt.kustomization.Resources, origin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "accumulating resources")
|
return nil, errors.Wrap(err, "accumulating resources")
|
||||||
}
|
}
|
||||||
ra, err = kt.accumulateComponents(ra, kt.kustomization.Components)
|
ra, err = kt.accumulateComponents(ra, kt.kustomization.Components, origin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "accumulating components")
|
return nil, errors.Wrap(err, "accumulating components")
|
||||||
}
|
}
|
||||||
@@ -247,7 +260,7 @@ func (kt *KustTarget) configureExternalGenerators() ([]resmap.Generator, error)
|
|||||||
}
|
}
|
||||||
ra.AppendAll(rm)
|
ra.AppendAll(rm)
|
||||||
}
|
}
|
||||||
ra, err := kt.accumulateResources(ra, generatorPaths)
|
ra, err := kt.accumulateResources(ra, generatorPaths, &resource.Origin{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -283,8 +296,7 @@ func (kt *KustTarget) configureExternalTransformers(transformers []string) ([]re
|
|||||||
}
|
}
|
||||||
ra.AppendAll(rm)
|
ra.AppendAll(rm)
|
||||||
}
|
}
|
||||||
ra, err := kt.accumulateResources(ra, transformerPaths)
|
ra, err := kt.accumulateResources(ra, transformerPaths, &resource.Origin{})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -303,16 +315,18 @@ func (kt *KustTarget) runValidators(ra *accumulator.ResAccumulator) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
new := ra.ResMap().DeepCopy()
|
newMap := ra.ResMap().DeepCopy()
|
||||||
kt.removeValidatedByLabel(new)
|
if err = kt.removeValidatedByLabel(newMap); err != nil {
|
||||||
if err = orignal.ErrorIfNotEqualSets(new); err != nil {
|
return err
|
||||||
|
}
|
||||||
|
if err = orignal.ErrorIfNotEqualSets(newMap); err != nil {
|
||||||
return fmt.Errorf("validator shouldn't modify the resource map: %v", err)
|
return fmt.Errorf("validator shouldn't modify the resource map: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) {
|
func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) error {
|
||||||
resources := rm.Resources()
|
resources := rm.Resources()
|
||||||
for _, r := range resources {
|
for _, r := range resources {
|
||||||
labels := r.GetLabels()
|
labels := r.GetLabels()
|
||||||
@@ -320,27 +334,26 @@ func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
delete(labels, konfig.ValidatedByLabelKey)
|
delete(labels, konfig.ValidatedByLabelKey)
|
||||||
if len(labels) == 0 {
|
if err := r.SetLabels(labels); err != nil {
|
||||||
r.SetLabels(nil)
|
return err
|
||||||
} else {
|
|
||||||
r.SetLabels(labels)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// accumulateResources fills the given resourceAccumulator
|
// accumulateResources fills the given resourceAccumulator
|
||||||
// with resources read from the given list of paths.
|
// with resources read from the given list of paths.
|
||||||
func (kt *KustTarget) accumulateResources(
|
func (kt *KustTarget) accumulateResources(
|
||||||
ra *accumulator.ResAccumulator, paths []string) (*accumulator.ResAccumulator, error) {
|
ra *accumulator.ResAccumulator, paths []string, origin *resource.Origin) (*accumulator.ResAccumulator, error) {
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
// try loading resource as file then as base (directory or git repository)
|
// try loading resource as file then as base (directory or git repository)
|
||||||
if errF := kt.accumulateFile(ra, path); errF != nil {
|
if errF := kt.accumulateFile(ra, path, origin); errF != nil {
|
||||||
ldr, err := kt.ldr.New(path)
|
ldr, err := kt.ldr.New(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(
|
return nil, errors.Wrapf(
|
||||||
err, "accumulation err='%s'", errF.Error())
|
err, "accumulation err='%s'", errF.Error())
|
||||||
}
|
}
|
||||||
ra, err = kt.accumulateDirectory(ra, ldr, false)
|
ra, err = kt.accumulateDirectory(ra, ldr, origin.Append(path), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(
|
return nil, errors.Wrapf(
|
||||||
err, "accumulation err='%s'", errF.Error())
|
err, "accumulation err='%s'", errF.Error())
|
||||||
@@ -353,7 +366,7 @@ func (kt *KustTarget) accumulateResources(
|
|||||||
// accumulateResources fills the given resourceAccumulator
|
// accumulateResources fills the given resourceAccumulator
|
||||||
// with resources read from the given list of paths.
|
// with resources read from the given list of paths.
|
||||||
func (kt *KustTarget) accumulateComponents(
|
func (kt *KustTarget) accumulateComponents(
|
||||||
ra *accumulator.ResAccumulator, paths []string) (*accumulator.ResAccumulator, error) {
|
ra *accumulator.ResAccumulator, paths []string, origin *resource.Origin) (*accumulator.ResAccumulator, error) {
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
// Components always refer to directories
|
// Components always refer to directories
|
||||||
ldr, errL := kt.ldr.New(path)
|
ldr, errL := kt.ldr.New(path)
|
||||||
@@ -361,7 +374,8 @@ func (kt *KustTarget) accumulateComponents(
|
|||||||
return nil, fmt.Errorf("loader.New %q", errL)
|
return nil, fmt.Errorf("loader.New %q", errL)
|
||||||
}
|
}
|
||||||
var errD error
|
var errD error
|
||||||
ra, errD = kt.accumulateDirectory(ra, ldr, true)
|
origin.Path = filepath.Join(origin.Path, path)
|
||||||
|
ra, errD = kt.accumulateDirectory(ra, ldr, origin, true)
|
||||||
if errD != nil {
|
if errD != nil {
|
||||||
return nil, fmt.Errorf("accumulateDirectory: %q", errD)
|
return nil, fmt.Errorf("accumulateDirectory: %q", errD)
|
||||||
}
|
}
|
||||||
@@ -370,7 +384,7 @@ func (kt *KustTarget) accumulateComponents(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) accumulateDirectory(
|
func (kt *KustTarget) accumulateDirectory(
|
||||||
ra *accumulator.ResAccumulator, ldr ifc.Loader, isComponent bool) (*accumulator.ResAccumulator, error) {
|
ra *accumulator.ResAccumulator, ldr ifc.Loader, origin *resource.Origin, isComponent bool) (*accumulator.ResAccumulator, error) {
|
||||||
defer ldr.Cleanup()
|
defer ldr.Cleanup()
|
||||||
subKt := NewKustTarget(ldr, kt.validator, kt.rFactory, kt.pLdr)
|
subKt := NewKustTarget(ldr, kt.validator, kt.rFactory, kt.pLdr)
|
||||||
err := subKt.Load()
|
err := subKt.Load()
|
||||||
@@ -378,6 +392,7 @@ func (kt *KustTarget) accumulateDirectory(
|
|||||||
return nil, errors.Wrapf(
|
return nil, errors.Wrapf(
|
||||||
err, "couldn't make target for path '%s'", ldr.Root())
|
err, "couldn't make target for path '%s'", ldr.Root())
|
||||||
}
|
}
|
||||||
|
subKt.kustomization.BuildMetadata = kt.kustomization.BuildMetadata
|
||||||
var bytes []byte
|
var bytes []byte
|
||||||
path := ldr.Root()
|
path := ldr.Root()
|
||||||
if openApiPath, exists := subKt.Kustomization().OpenAPI["path"]; exists {
|
if openApiPath, exists := subKt.Kustomization().OpenAPI["path"]; exists {
|
||||||
@@ -401,12 +416,12 @@ func (kt *KustTarget) accumulateDirectory(
|
|||||||
var subRa *accumulator.ResAccumulator
|
var subRa *accumulator.ResAccumulator
|
||||||
if isComponent {
|
if isComponent {
|
||||||
// Components don't create a new accumulator: the kustomization directives are added to the current accumulator
|
// Components don't create a new accumulator: the kustomization directives are added to the current accumulator
|
||||||
subRa, err = subKt.accumulateTarget(ra)
|
subRa, err = subKt.accumulateTarget(ra, origin)
|
||||||
ra = accumulator.MakeEmptyAccumulator()
|
ra = accumulator.MakeEmptyAccumulator()
|
||||||
} else {
|
} else {
|
||||||
// Child Kustomizations create a new accumulator which resolves their kustomization directives, which will later
|
// Child Kustomizations create a new accumulator which resolves their kustomization directives, which will later
|
||||||
// be merged into the current accumulator.
|
// be merged into the current accumulator.
|
||||||
subRa, err = subKt.AccumulateTarget()
|
subRa, err = subKt.AccumulateTarget(origin)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(
|
return nil, errors.Wrapf(
|
||||||
@@ -421,11 +436,18 @@ func (kt *KustTarget) accumulateDirectory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) accumulateFile(
|
func (kt *KustTarget) accumulateFile(
|
||||||
ra *accumulator.ResAccumulator, path string) error {
|
ra *accumulator.ResAccumulator, path string, origin *resource.Origin) error {
|
||||||
resources, err := kt.rFactory.FromFile(kt.ldr, path)
|
resources, err := kt.rFactory.FromFile(kt.ldr, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "accumulating resources from '%s'", path)
|
return errors.Wrapf(err, "accumulating resources from '%s'", path)
|
||||||
}
|
}
|
||||||
|
if utils.StringSliceContains(kt.kustomization.BuildMetadata, "originAnnotations") {
|
||||||
|
origin = origin.Append(path)
|
||||||
|
err = resources.AnnotateAll(utils.OriginAnnotation, origin.String())
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "cannot add path annotation for '%s'", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
err = ra.AppendAll(resources)
|
err = ra.AppendAll(resources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "merging resources from '%s'", path)
|
return errors.Wrapf(err, "merging resources from '%s'", path)
|
||||||
|
|||||||
@@ -255,5 +255,5 @@ metadata:
|
|||||||
actual.RemoveBuildAnnotations()
|
actual.RemoveBuildAnnotations()
|
||||||
actYaml, err := actual.AsYaml()
|
actYaml, err := actual.AsYaml()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, expYaml, actYaml)
|
assert.Equal(t, string(expYaml), string(actYaml))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ package target_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||||
"sigs.k8s.io/kustomize/api/internal/target"
|
"sigs.k8s.io/kustomize/api/internal/target"
|
||||||
fLdr "sigs.k8s.io/kustomize/api/loader"
|
fLdr "sigs.k8s.io/kustomize/api/loader"
|
||||||
@@ -14,6 +13,7 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeAndLoadKustTarget(
|
func makeAndLoadKustTarget(
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// To simplify tests, these vars specified in alphabetical order.
|
// To simplify tests, these vars specified in alphabetical order.
|
||||||
@@ -65,7 +66,7 @@ vars:
|
|||||||
apiVersion: v300
|
apiVersion: v300
|
||||||
`)
|
`)
|
||||||
ra, err := makeAndLoadKustTarget(
|
ra, err := makeAndLoadKustTarget(
|
||||||
t, th.GetFSys(), "/app").AccumulateTarget()
|
t, th.GetFSys(), "/app").AccumulateTarget(&resource.Origin{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
}
|
}
|
||||||
@@ -120,7 +121,7 @@ resources:
|
|||||||
`)
|
`)
|
||||||
|
|
||||||
ra, err := makeAndLoadKustTarget(
|
ra, err := makeAndLoadKustTarget(
|
||||||
t, th.GetFSys(), "/app/overlays/o2").AccumulateTarget()
|
t, th.GetFSys(), "/app/overlays/o2").AccumulateTarget(&resource.Origin{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
}
|
}
|
||||||
@@ -177,7 +178,7 @@ resources:
|
|||||||
- ../o1
|
- ../o1
|
||||||
`)
|
`)
|
||||||
_, err := makeAndLoadKustTarget(
|
_, err := makeAndLoadKustTarget(
|
||||||
t, th.GetFSys(), "/app/overlays/o2").AccumulateTarget()
|
t, th.GetFSys(), "/app/overlays/o2").AccumulateTarget(&resource.Origin{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected var collision")
|
t.Fatalf("expected var collision")
|
||||||
}
|
}
|
||||||
|
|||||||
23
api/internal/utils/annotations.go
Normal file
23
api/internal/utils/annotations.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "sigs.k8s.io/kustomize/api/konfig"
|
||||||
|
|
||||||
|
const (
|
||||||
|
BuildAnnotationPreviousKinds = konfig.ConfigAnnoDomain + "/previousKinds"
|
||||||
|
BuildAnnotationPreviousNames = konfig.ConfigAnnoDomain + "/previousNames"
|
||||||
|
BuildAnnotationPrefixes = konfig.ConfigAnnoDomain + "/prefixes"
|
||||||
|
BuildAnnotationSuffixes = konfig.ConfigAnnoDomain + "/suffixes"
|
||||||
|
BuildAnnotationPreviousNamespaces = konfig.ConfigAnnoDomain + "/previousNamespaces"
|
||||||
|
BuildAnnotationsRefBy = konfig.ConfigAnnoDomain + "/refBy"
|
||||||
|
BuildAnnotationsGenBehavior = konfig.ConfigAnnoDomain + "/generatorBehavior"
|
||||||
|
BuildAnnotationsGenAddHashSuffix = konfig.ConfigAnnoDomain + "/needsHashSuffix"
|
||||||
|
|
||||||
|
// the following are only for patches, to specify whether they can change names
|
||||||
|
// and kinds of their targets
|
||||||
|
BuildAnnotationAllowNameChange = konfig.ConfigAnnoDomain + "/allowNameChange"
|
||||||
|
BuildAnnotationAllowKindChange = konfig.ConfigAnnoDomain + "/allowKindChange"
|
||||||
|
|
||||||
|
OriginAnnotation = "config.kubernetes.io/origin"
|
||||||
|
|
||||||
|
Enabled = "enabled"
|
||||||
|
)
|
||||||
64
api/internal/utils/makeResIds.go
Normal file
64
api/internal/utils/makeResIds.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MakeResIds returns all of an RNode's current and previous Ids
|
||||||
|
func MakeResIds(n *yaml.RNode) ([]resid.ResId, error) {
|
||||||
|
var result []resid.ResId
|
||||||
|
apiVersion := n.Field(yaml.APIVersionField)
|
||||||
|
var group, version string
|
||||||
|
if apiVersion != nil {
|
||||||
|
group, version = resid.ParseGroupVersion(yaml.GetValue(apiVersion.Value))
|
||||||
|
}
|
||||||
|
result = append(result, resid.NewResIdWithNamespace(
|
||||||
|
resid.Gvk{Group: group, Version: version, Kind: n.GetKind()}, n.GetName(), n.GetNamespace()),
|
||||||
|
)
|
||||||
|
prevIds, err := PrevIds(n)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, prevIds...)
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevIds returns all of an RNode's previous Ids
|
||||||
|
func PrevIds(n *yaml.RNode) ([]resid.ResId, error) {
|
||||||
|
var ids []resid.ResId
|
||||||
|
// TODO: merge previous names and namespaces into one list of
|
||||||
|
// pairs on one annotation so there is no chance of error
|
||||||
|
annotations := n.GetAnnotations()
|
||||||
|
if _, ok := annotations[BuildAnnotationPreviousNames]; !ok {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
names := strings.Split(annotations[BuildAnnotationPreviousNames], ",")
|
||||||
|
ns := strings.Split(annotations[BuildAnnotationPreviousNamespaces], ",")
|
||||||
|
kinds := strings.Split(annotations[BuildAnnotationPreviousKinds], ",")
|
||||||
|
// This should never happen
|
||||||
|
if len(names) != len(ns) || len(names) != len(kinds) {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"number of previous names, " +
|
||||||
|
"number of previous namespaces, " +
|
||||||
|
"number of previous kinds not equal")
|
||||||
|
}
|
||||||
|
for i := range names {
|
||||||
|
meta, err := n.GetMeta()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
group, version := resid.ParseGroupVersion(meta.APIVersion)
|
||||||
|
gvk := resid.Gvk{
|
||||||
|
Group: group,
|
||||||
|
Version: version,
|
||||||
|
Kind: kinds[i],
|
||||||
|
}
|
||||||
|
ids = append(ids, resid.NewResIdWithNamespace(
|
||||||
|
gvk, names[i], ns[i]))
|
||||||
|
}
|
||||||
|
return ids, nil
|
||||||
|
}
|
||||||
@@ -5,18 +5,60 @@ package utils
|
|||||||
|
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
// PathSplitter splits a slash delimited string, permitting escaped slashes.
|
// TODO: Move these to kyaml
|
||||||
func PathSplitter(path string) []string {
|
|
||||||
ps := strings.Split(path, "/")
|
// PathSplitter splits a delimited string, permitting escaped delimiters.
|
||||||
|
func PathSplitter(path string, delimiter string) []string {
|
||||||
|
ps := strings.Split(path, delimiter)
|
||||||
var res []string
|
var res []string
|
||||||
res = append(res, ps[0])
|
res = append(res, ps[0])
|
||||||
for i := 1; i < len(ps); i++ {
|
for i := 1; i < len(ps); i++ {
|
||||||
last := len(res) - 1
|
last := len(res) - 1
|
||||||
if strings.HasSuffix(res[last], `\`) {
|
if strings.HasSuffix(res[last], `\`) {
|
||||||
res[last] = strings.TrimSuffix(res[last], `\`) + "/" + ps[i]
|
res[last] = strings.TrimSuffix(res[last], `\`) + delimiter + ps[i]
|
||||||
} else {
|
} else {
|
||||||
res = append(res, ps[i])
|
res = append(res, ps[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SmarterPathSplitter splits a path, retaining bracketed elements.
|
||||||
|
// If the element is a list entry identifier (defined by the '='),
|
||||||
|
// it will retain the brackets.
|
||||||
|
// E.g. "[name=com.foo.someapp]" survives as one thing after splitting
|
||||||
|
// "spec.template.spec.containers.[name=com.foo.someapp].image"
|
||||||
|
// See kyaml/yaml/match.go for use of list entry identifiers.
|
||||||
|
// If the element is a mapping entry identifier, it will remove the
|
||||||
|
// brackets.
|
||||||
|
// E.g. "a.b.c" survives as one thing after splitting
|
||||||
|
// "metadata.annotations.[a.b.c]
|
||||||
|
// This function uses `PathSplitter`, so it also respects escaped delimiters.
|
||||||
|
func SmarterPathSplitter(path string, delimiter string) []string {
|
||||||
|
var result []string
|
||||||
|
split := PathSplitter(path, delimiter)
|
||||||
|
|
||||||
|
for i := 0; i < len(split); i++ {
|
||||||
|
elem := split[i]
|
||||||
|
if strings.HasPrefix(elem, "[") && !strings.HasSuffix(elem, "]") {
|
||||||
|
// continue until we find the matching "]"
|
||||||
|
bracketed := []string{elem}
|
||||||
|
for i < len(split)-1 {
|
||||||
|
i++
|
||||||
|
bracketed = append(bracketed, split[i])
|
||||||
|
if strings.HasSuffix(split[i], "]") {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bracketedStr := strings.Join(bracketed, delimiter)
|
||||||
|
if strings.Contains(bracketedStr, "=") {
|
||||||
|
result = append(result, bracketedStr)
|
||||||
|
} else {
|
||||||
|
result = append(result, strings.Trim(bracketedStr, "[]"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = append(result, elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,6 +44,51 @@ func TestPathSplitter(t *testing.T) {
|
|||||||
"nginx.ingress.kubernetes.io/auth-secret"},
|
"nginx.ingress.kubernetes.io/auth-secret"},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
assert.Equal(t, tc.exp, PathSplitter(tc.path))
|
assert.Equal(t, tc.exp, PathSplitter(tc.path, "/"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSmarterPathSplitter(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
input string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
"simple": {
|
||||||
|
input: "spec.replicas",
|
||||||
|
expected: []string{"spec", "replicas"},
|
||||||
|
},
|
||||||
|
"sequence": {
|
||||||
|
input: "spec.data.[name=first].key",
|
||||||
|
expected: []string{"spec", "data", "[name=first]", "key"},
|
||||||
|
},
|
||||||
|
"key, value with . prefix": {
|
||||||
|
input: "spec.data.[.name=.first].key",
|
||||||
|
expected: []string{"spec", "data", "[.name=.first]", "key"},
|
||||||
|
},
|
||||||
|
"key, value with . suffix": {
|
||||||
|
input: "spec.data.[name.=first.].key",
|
||||||
|
expected: []string{"spec", "data", "[name.=first.]", "key"},
|
||||||
|
},
|
||||||
|
"multiple '.' in value": {
|
||||||
|
input: "spec.data.[name=f.i.r.s.t.].key",
|
||||||
|
expected: []string{"spec", "data", "[name=f.i.r.s.t.]", "key"},
|
||||||
|
},
|
||||||
|
"with escaped delimiter": {
|
||||||
|
input: `spec\.replicas`,
|
||||||
|
expected: []string{`spec.replicas`},
|
||||||
|
},
|
||||||
|
"unmatched bracket": {
|
||||||
|
input: "spec.data.[name=f.i.[r.s.t..key",
|
||||||
|
expected: []string{"spec", "data", "[name=f.i.[r.s.t..key"},
|
||||||
|
},
|
||||||
|
"mapping value with .": {
|
||||||
|
input: "metadata.annotations.[a.b.c/d.e.f-g.]",
|
||||||
|
expected: []string{"metadata", "annotations", "a.b.c/d.e.f-g."},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for tn, tc := range testCases {
|
||||||
|
t.Run(tn, func(t *testing.T) {
|
||||||
|
assert.Equal(t, tc.expected, SmarterPathSplitter(tc.input, "."))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
44
api/internal/utils/stringslice.go
Normal file
44
api/internal/utils/stringslice.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
// StringSliceIndex returns the index of the str, else -1.
|
||||||
|
func StringSliceIndex(slice []string, str string) int {
|
||||||
|
for i := range slice {
|
||||||
|
if slice[i] == str {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSliceContains returns true if the slice has the string.
|
||||||
|
func StringSliceContains(slice []string, str string) bool {
|
||||||
|
for _, s := range slice {
|
||||||
|
if s == str {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SameEndingSubSlice returns true if the slices end the same way, e.g.
|
||||||
|
// {"a", "b", "c"}, {"b", "c"} => true
|
||||||
|
// {"a", "b", "c"}, {"a", "b"} => false
|
||||||
|
// If one slice is empty and the other is not, return false.
|
||||||
|
func SameEndingSubSlice(shortest, longest []string) bool {
|
||||||
|
if len(shortest) > len(longest) {
|
||||||
|
longest, shortest = shortest, longest
|
||||||
|
}
|
||||||
|
diff := len(longest) - len(shortest)
|
||||||
|
if len(shortest) == 0 {
|
||||||
|
return diff == 0
|
||||||
|
}
|
||||||
|
for i := len(shortest) - 1; i >= 0; i-- {
|
||||||
|
if longest[i+diff] != shortest[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
37
api/internal/utils/stringslice_test.go
Normal file
37
api/internal/utils/stringslice_test.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package utils_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
. "sigs.k8s.io/kustomize/api/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStringSliceIndex(t *testing.T) {
|
||||||
|
assert.Equal(t, 0, StringSliceIndex([]string{"a", "b"}, "a"))
|
||||||
|
assert.Equal(t, 1, StringSliceIndex([]string{"a", "b"}, "b"))
|
||||||
|
assert.Equal(t, -1, StringSliceIndex([]string{"a", "b"}, "c"))
|
||||||
|
assert.Equal(t, -1, StringSliceIndex([]string{}, "c"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringSliceContains(t *testing.T) {
|
||||||
|
assert.True(t, StringSliceContains([]string{"a", "b"}, "a"))
|
||||||
|
assert.True(t, StringSliceContains([]string{"a", "b"}, "b"))
|
||||||
|
assert.False(t, StringSliceContains([]string{"a", "b"}, "c"))
|
||||||
|
assert.False(t, StringSliceContains([]string{}, "c"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSameEndingSubarray(t *testing.T) {
|
||||||
|
assert.True(t, SameEndingSubSlice([]string{"", "a", "b"}, []string{"a", "b"}))
|
||||||
|
assert.True(t, SameEndingSubSlice([]string{"a", "b", ""}, []string{"b", ""}))
|
||||||
|
assert.True(t, SameEndingSubSlice([]string{"a", "b"}, []string{"a", "b"}))
|
||||||
|
assert.True(t, SameEndingSubSlice([]string{"a", "b"}, []string{"b"}))
|
||||||
|
assert.True(t, SameEndingSubSlice([]string{"b"}, []string{"a", "b"}))
|
||||||
|
assert.True(t, SameEndingSubSlice([]string{}, []string{}))
|
||||||
|
assert.False(t, SameEndingSubSlice([]string{"a", "b"}, []string{"b", "a"}))
|
||||||
|
assert.False(t, SameEndingSubSlice([]string{"a", "b"}, []string{}))
|
||||||
|
assert.False(t, SameEndingSubSlice([]string{"a", "b"}, []string{""}))
|
||||||
|
}
|
||||||
@@ -3,9 +3,6 @@
|
|||||||
|
|
||||||
package builtinpluginconsts
|
package builtinpluginconsts
|
||||||
|
|
||||||
// TODO: rename 'fieldSpecs' to 'referrers' for clarity.
|
|
||||||
// This will, however, break anyone using a custom config.
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
nameReferenceFieldSpecs = `
|
nameReferenceFieldSpecs = `
|
||||||
nameReference:
|
nameReference:
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package konfig provides configuration methods and constants
|
// Package konfig provides configuration methods and constants
|
||||||
// for the kustomize API.
|
// for the kustomize API, e.g. the set of file names to look for
|
||||||
|
// to identify a kustomization root.
|
||||||
package konfig
|
package konfig
|
||||||
|
|||||||
@@ -31,11 +31,12 @@ const (
|
|||||||
// A program name, for use in help, finding the XDG_CONFIG_DIR, etc.
|
// A program name, for use in help, finding the XDG_CONFIG_DIR, etc.
|
||||||
ProgramName = "kustomize"
|
ProgramName = "kustomize"
|
||||||
|
|
||||||
// ConfigAnnoDomain is configuration-related annotation namespace.
|
// ConfigAnnoDomain is internal configuration-related annotation namespace.
|
||||||
ConfigAnnoDomain = "config.kubernetes.io"
|
// See https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md.
|
||||||
|
ConfigAnnoDomain = "internal.config.kubernetes.io"
|
||||||
|
|
||||||
// If a resource has this annotation, kustomize will drop it.
|
// If a resource has this annotation, kustomize will drop it.
|
||||||
IgnoredByKustomizeAnnotation = ConfigAnnoDomain + "/local-config"
|
IgnoredByKustomizeAnnotation = "config.kubernetes.io/local-config"
|
||||||
|
|
||||||
// Label key that indicates the resources are built from Kustomize
|
// Label key that indicates the resources are built from Kustomize
|
||||||
ManagedbyLabelKey = "app.kubernetes.io/managed-by"
|
ManagedbyLabelKey = "app.kubernetes.io/managed-by"
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -9,20 +9,20 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDefaultAbsPluginHome_NoKustomizePluginHomeEnv(t *testing.T) {
|
func TestDefaultAbsPluginHome_NoKustomizePluginHomeEnv(t *testing.T) {
|
||||||
fSys := filesys.MakeFsInMemory()
|
fSys := filesys.MakeFsInMemory()
|
||||||
keep, isSet := os.LookupEnv(KustomizePluginHomeEnv)
|
keep, isSet := os.LookupEnv(KustomizePluginHomeEnv)
|
||||||
if isSet {
|
if isSet {
|
||||||
_ = os.Unsetenv(KustomizePluginHomeEnv)
|
unsetenv(t, KustomizePluginHomeEnv)
|
||||||
}
|
}
|
||||||
_, err := DefaultAbsPluginHome(fSys)
|
_, err := DefaultAbsPluginHome(fSys)
|
||||||
if isSet {
|
if isSet {
|
||||||
os.Setenv(KustomizePluginHomeEnv, keep)
|
setenv(t, KustomizePluginHomeEnv, keep)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected err")
|
t.Fatalf("expected err")
|
||||||
@@ -43,13 +43,13 @@ func TestDefaultAbsPluginHome_NoKustomizePluginHomeEnv(t *testing.T) {
|
|||||||
|
|
||||||
func TestDefaultAbsPluginHome_EmptyKustomizePluginHomeEnv(t *testing.T) {
|
func TestDefaultAbsPluginHome_EmptyKustomizePluginHomeEnv(t *testing.T) {
|
||||||
keep, isSet := os.LookupEnv(KustomizePluginHomeEnv)
|
keep, isSet := os.LookupEnv(KustomizePluginHomeEnv)
|
||||||
os.Setenv(KustomizePluginHomeEnv, "")
|
setenv(t, KustomizePluginHomeEnv, "")
|
||||||
|
|
||||||
_, err := DefaultAbsPluginHome(filesys.MakeFsInMemory())
|
_, err := DefaultAbsPluginHome(filesys.MakeFsInMemory())
|
||||||
if !isSet {
|
if !isSet {
|
||||||
_ = os.Unsetenv(KustomizePluginHomeEnv)
|
unsetenv(t, KustomizePluginHomeEnv)
|
||||||
} else {
|
} else {
|
||||||
_ = os.Setenv(KustomizePluginHomeEnv, keep)
|
setenv(t, KustomizePluginHomeEnv, keep)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected err")
|
t.Fatalf("expected err")
|
||||||
@@ -65,16 +65,15 @@ func TestDefaultAbsPluginHome_WithKustomizePluginHomeEnv(t *testing.T) {
|
|||||||
keep, isSet := os.LookupEnv(KustomizePluginHomeEnv)
|
keep, isSet := os.LookupEnv(KustomizePluginHomeEnv)
|
||||||
if !isSet {
|
if !isSet {
|
||||||
keep = "whatever"
|
keep = "whatever"
|
||||||
os.Setenv(KustomizePluginHomeEnv, keep)
|
setenv(t, KustomizePluginHomeEnv, keep)
|
||||||
}
|
}
|
||||||
fSys.Mkdir(keep)
|
err := fSys.Mkdir(keep)
|
||||||
|
require.NoError(t, err)
|
||||||
h, err := DefaultAbsPluginHome(fSys)
|
h, err := DefaultAbsPluginHome(fSys)
|
||||||
if !isSet {
|
if !isSet {
|
||||||
_ = os.Unsetenv(KustomizePluginHomeEnv)
|
unsetenv(t, KustomizePluginHomeEnv)
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected err: %v", err)
|
|
||||||
}
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
if h != keep {
|
if h != keep {
|
||||||
t.Fatalf("unexpected config dir: %s", h)
|
t.Fatalf("unexpected config dir: %s", h)
|
||||||
}
|
}
|
||||||
@@ -85,13 +84,14 @@ func TestDefaultAbsPluginHomeWithXdg(t *testing.T) {
|
|||||||
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
||||||
if !isSet {
|
if !isSet {
|
||||||
keep = "whatever"
|
keep = "whatever"
|
||||||
os.Setenv(XdgConfigHomeEnv, keep)
|
setenv(t, XdgConfigHomeEnv, keep)
|
||||||
}
|
}
|
||||||
configDir := filepath.Join(keep, ProgramName, RelPluginHome)
|
configDir := filepath.Join(keep, ProgramName, RelPluginHome)
|
||||||
fSys.Mkdir(configDir)
|
err := fSys.Mkdir(configDir)
|
||||||
|
require.NoError(t, err)
|
||||||
h, err := DefaultAbsPluginHome(fSys)
|
h, err := DefaultAbsPluginHome(fSys)
|
||||||
if !isSet {
|
if !isSet {
|
||||||
_ = os.Unsetenv(XdgConfigHomeEnv)
|
unsetenv(t, XdgConfigHomeEnv)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected err: %v", err)
|
t.Fatalf("unexpected err: %v", err)
|
||||||
@@ -105,11 +105,11 @@ func TestDefaultAbsPluginHomeNoConfig(t *testing.T) {
|
|||||||
fSys := filesys.MakeFsInMemory()
|
fSys := filesys.MakeFsInMemory()
|
||||||
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
||||||
if isSet {
|
if isSet {
|
||||||
_ = os.Unsetenv(XdgConfigHomeEnv)
|
unsetenv(t, XdgConfigHomeEnv)
|
||||||
}
|
}
|
||||||
_, err := DefaultAbsPluginHome(fSys)
|
_, err := DefaultAbsPluginHome(fSys)
|
||||||
if isSet {
|
if isSet {
|
||||||
os.Setenv(XdgConfigHomeEnv, keep)
|
setenv(t, XdgConfigHomeEnv, keep)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected err")
|
t.Fatalf("expected err")
|
||||||
@@ -121,13 +121,13 @@ func TestDefaultAbsPluginHomeNoConfig(t *testing.T) {
|
|||||||
|
|
||||||
func TestDefaultAbsPluginHomeEmptyXdgConfig(t *testing.T) {
|
func TestDefaultAbsPluginHomeEmptyXdgConfig(t *testing.T) {
|
||||||
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
||||||
os.Setenv(XdgConfigHomeEnv, "")
|
setenv(t, XdgConfigHomeEnv, "")
|
||||||
if isSet {
|
if isSet {
|
||||||
_ = os.Unsetenv(XdgConfigHomeEnv)
|
unsetenv(t, XdgConfigHomeEnv)
|
||||||
}
|
}
|
||||||
_, err := DefaultAbsPluginHome(filesys.MakeFsInMemory())
|
_, err := DefaultAbsPluginHome(filesys.MakeFsInMemory())
|
||||||
if isSet {
|
if isSet {
|
||||||
os.Setenv(XdgConfigHomeEnv, keep)
|
setenv(t, XdgConfigHomeEnv, keep)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected err")
|
t.Fatalf("expected err")
|
||||||
@@ -142,14 +142,16 @@ func TestDefaultAbsPluginHomeNoXdgWithDotConfig(t *testing.T) {
|
|||||||
fSys := filesys.MakeFsInMemory()
|
fSys := filesys.MakeFsInMemory()
|
||||||
configDir := filepath.Join(
|
configDir := filepath.Join(
|
||||||
HomeDir(), XdgConfigHomeEnvDefault, ProgramName, RelPluginHome)
|
HomeDir(), XdgConfigHomeEnvDefault, ProgramName, RelPluginHome)
|
||||||
fSys.Mkdir(configDir)
|
err := fSys.Mkdir(configDir)
|
||||||
|
require.NoError(t, err)
|
||||||
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
||||||
if isSet {
|
if isSet {
|
||||||
_ = os.Unsetenv(XdgConfigHomeEnv)
|
unsetenv(t, XdgConfigHomeEnv)
|
||||||
}
|
}
|
||||||
s, _ := DefaultAbsPluginHome(fSys)
|
s, err := DefaultAbsPluginHome(fSys)
|
||||||
|
require.NoError(t, err)
|
||||||
if isSet {
|
if isSet {
|
||||||
os.Setenv(XdgConfigHomeEnv, keep)
|
setenv(t, XdgConfigHomeEnv, keep)
|
||||||
}
|
}
|
||||||
if s != configDir {
|
if s != configDir {
|
||||||
t.Fatalf("unexpected config dir: %s", s)
|
t.Fatalf("unexpected config dir: %s", s)
|
||||||
@@ -160,16 +162,26 @@ func TestDefaultAbsPluginHomeNoXdgJustHomeDir(t *testing.T) {
|
|||||||
fSys := filesys.MakeFsInMemory()
|
fSys := filesys.MakeFsInMemory()
|
||||||
configDir := filepath.Join(
|
configDir := filepath.Join(
|
||||||
HomeDir(), ProgramName, RelPluginHome)
|
HomeDir(), ProgramName, RelPluginHome)
|
||||||
fSys.Mkdir(configDir)
|
err := fSys.Mkdir(configDir)
|
||||||
|
require.NoError(t, err)
|
||||||
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
keep, isSet := os.LookupEnv(XdgConfigHomeEnv)
|
||||||
if isSet {
|
if isSet {
|
||||||
_ = os.Unsetenv(XdgConfigHomeEnv)
|
unsetenv(t, XdgConfigHomeEnv)
|
||||||
}
|
}
|
||||||
s, _ := DefaultAbsPluginHome(fSys)
|
s, err := DefaultAbsPluginHome(fSys)
|
||||||
|
require.NoError(t, err)
|
||||||
if isSet {
|
if isSet {
|
||||||
os.Setenv(XdgConfigHomeEnv, keep)
|
setenv(t, XdgConfigHomeEnv, keep)
|
||||||
}
|
}
|
||||||
if s != configDir {
|
if s != configDir {
|
||||||
t.Fatalf("unexpected config dir: %s", s)
|
t.Fatalf("unexpected config dir: %s", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setenv(t *testing.T, key, value string) {
|
||||||
|
require.NoError(t, os.Setenv(key, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsetenv(t *testing.T, key string) {
|
||||||
|
require.NoError(t, os.Unsetenv(key))
|
||||||
|
}
|
||||||
|
|||||||
265
api/krusty/buildmetadata_test.go
Normal file
265
api/krusty/buildmetadata_test.go
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package krusty_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
_ "sigs.k8s.io/kustomize/api/krusty"
|
||||||
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAnnoOriginLocalFiles(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteF("service.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: myService
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 7002
|
||||||
|
`)
|
||||||
|
th.WriteK(".", `
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- service.yaml
|
||||||
|
buildMetadata: [originAnnotations]
|
||||||
|
`)
|
||||||
|
options := th.MakeDefaultOptions()
|
||||||
|
m := th.Run(".", options)
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/origin: |
|
||||||
|
path: service.yaml
|
||||||
|
name: myService
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 7002
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAnnoOriginLocalFilesWithOverlay(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteK("base", `
|
||||||
|
namePrefix: b-
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- role.yaml
|
||||||
|
- service.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("base/service.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: myService
|
||||||
|
`)
|
||||||
|
th.WriteF("base/namespace.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: myNs
|
||||||
|
`)
|
||||||
|
th.WriteF("base/role.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: myRole
|
||||||
|
`)
|
||||||
|
th.WriteF("base/deployment.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: myDep
|
||||||
|
`)
|
||||||
|
th.WriteK("prod", `
|
||||||
|
namePrefix: p-
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
- service.yaml
|
||||||
|
- namespace.yaml
|
||||||
|
buildMetadata: [originAnnotations]
|
||||||
|
`)
|
||||||
|
th.WriteF("prod/service.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: myService2
|
||||||
|
`)
|
||||||
|
th.WriteF("prod/namespace.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: myNs2
|
||||||
|
`)
|
||||||
|
m := th.Run("prod", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/origin: |
|
||||||
|
path: ../base/namespace.yaml
|
||||||
|
name: myNs
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/origin: |
|
||||||
|
path: ../base/role.yaml
|
||||||
|
name: p-b-myRole
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/origin: |
|
||||||
|
path: ../base/service.yaml
|
||||||
|
name: p-b-myService
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/origin: |
|
||||||
|
path: ../base/deployment.yaml
|
||||||
|
name: p-b-myDep
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/origin: |
|
||||||
|
path: service.yaml
|
||||||
|
name: p-myService2
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/origin: |
|
||||||
|
path: namespace.yaml
|
||||||
|
name: myNs2
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a copy of TestGeneratorBasics in configmaps_test.go,
|
||||||
|
// except that we've enabled the addAnnoOrigin option
|
||||||
|
// (which doesn't do anything yet).
|
||||||
|
// TODO: Generated resources should receive the annotation
|
||||||
|
// config.kubernetes.io/origin: |
|
||||||
|
// generated-by: path/to/kustomization.yaml
|
||||||
|
func TestGeneratorWithAnnoOrigin(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteK(".", `
|
||||||
|
namePrefix: blah-
|
||||||
|
configMapGenerator:
|
||||||
|
- name: bob
|
||||||
|
literals:
|
||||||
|
- fruit=apple
|
||||||
|
- vegetable=broccoli
|
||||||
|
envs:
|
||||||
|
- foo.env
|
||||||
|
env: bar.env
|
||||||
|
files:
|
||||||
|
- passphrase=phrase.dat
|
||||||
|
- forces.txt
|
||||||
|
- name: json
|
||||||
|
literals:
|
||||||
|
- 'v2=[{"path": "var/druid/segment-cache"}]'
|
||||||
|
- >-
|
||||||
|
druid_segmentCache_locations=[{"path":
|
||||||
|
"var/druid/segment-cache",
|
||||||
|
"maxSize": 32000000000,
|
||||||
|
"freeSpacePercent": 1.0}]
|
||||||
|
secretGenerator:
|
||||||
|
- name: bob
|
||||||
|
literals:
|
||||||
|
- fruit=apple
|
||||||
|
- vegetable=broccoli
|
||||||
|
envs:
|
||||||
|
- foo.env
|
||||||
|
files:
|
||||||
|
- passphrase=phrase.dat
|
||||||
|
- forces.txt
|
||||||
|
env: bar.env
|
||||||
|
`)
|
||||||
|
th.WriteF("foo.env", `
|
||||||
|
MOUNTAIN=everest
|
||||||
|
OCEAN=pacific
|
||||||
|
`)
|
||||||
|
th.WriteF("bar.env", `
|
||||||
|
BIRD=falcon
|
||||||
|
`)
|
||||||
|
th.WriteF("phrase.dat", `
|
||||||
|
Life is short.
|
||||||
|
But the years are long.
|
||||||
|
Not while the evil days come not.
|
||||||
|
`)
|
||||||
|
th.WriteF("forces.txt", `
|
||||||
|
gravitational
|
||||||
|
electromagnetic
|
||||||
|
strong nuclear
|
||||||
|
weak nuclear
|
||||||
|
`)
|
||||||
|
opts := th.MakeDefaultOptions()
|
||||||
|
m := th.Run(".", opts)
|
||||||
|
th.AssertActualEqualsExpected(
|
||||||
|
m, `
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
BIRD: falcon
|
||||||
|
MOUNTAIN: everest
|
||||||
|
OCEAN: pacific
|
||||||
|
forces.txt: |2
|
||||||
|
|
||||||
|
gravitational
|
||||||
|
electromagnetic
|
||||||
|
strong nuclear
|
||||||
|
weak nuclear
|
||||||
|
fruit: apple
|
||||||
|
passphrase: |2
|
||||||
|
|
||||||
|
Life is short.
|
||||||
|
But the years are long.
|
||||||
|
Not while the evil days come not.
|
||||||
|
vegetable: broccoli
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: blah-bob-g9df72cd5b
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
druid_segmentCache_locations: '[{"path": "var/druid/segment-cache", "maxSize":
|
||||||
|
32000000000, "freeSpacePercent": 1.0}]'
|
||||||
|
v2: '[{"path": "var/druid/segment-cache"}]'
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: blah-json-5298bc8g99
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
BIRD: ZmFsY29u
|
||||||
|
MOUNTAIN: ZXZlcmVzdA==
|
||||||
|
OCEAN: cGFjaWZpYw==
|
||||||
|
forces.txt: |
|
||||||
|
CmdyYXZpdGF0aW9uYWwKZWxlY3Ryb21hZ25ldGljCnN0cm9uZyBudWNsZWFyCndlYWsgbn
|
||||||
|
VjbGVhcgo=
|
||||||
|
fruit: YXBwbGU=
|
||||||
|
passphrase: |
|
||||||
|
CkxpZmUgaXMgc2hvcnQuCkJ1dCB0aGUgeWVhcnMgYXJlIGxvbmcuCk5vdCB3aGlsZSB0aG
|
||||||
|
UgZXZpbCBkYXlzIGNvbWUgbm90Lgo=
|
||||||
|
vegetable: YnJvY2NvbGk=
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: blah-bob-58g62h555c
|
||||||
|
type: Opaque
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -1,17 +1,52 @@
|
|||||||
package krusty_test
|
package krusty_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFnExecGenerator(t *testing.T) {
|
const generateDeploymentDotSh = `#!/bin/sh
|
||||||
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
|
||||||
th := kusttest_test.MakeHarness(t)
|
|
||||||
|
|
||||||
th.WriteK(".", `
|
cat <<EOF
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
annotations:
|
||||||
|
tshirt-size: small # this injects the resource reservations
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nginx
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx
|
||||||
|
EOF
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestFnExecGenerator(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsOnDisk()
|
||||||
|
|
||||||
|
th := kusttest_test.MakeHarnessWithFs(t, fSys)
|
||||||
|
o := th.MakeOptionsPluginsEnabled()
|
||||||
|
o.PluginConfig.FnpLoadingOptions.EnableExec = true
|
||||||
|
|
||||||
|
tmpDir, err := filesys.NewTmpConfirmedDir()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
th.WriteK(tmpDir.String(), `
|
||||||
resources:
|
resources:
|
||||||
- short_secret.yaml
|
- short_secret.yaml
|
||||||
generators:
|
generators:
|
||||||
@@ -19,7 +54,8 @@ generators:
|
|||||||
`)
|
`)
|
||||||
|
|
||||||
// Create some additional resource just to make sure everything is added
|
// Create some additional resource just to make sure everything is added
|
||||||
th.WriteF("short_secret.yaml", `
|
th.WriteF(filepath.Join(tmpDir.String(), "short_secret.yaml"),
|
||||||
|
`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
@@ -32,22 +68,25 @@ stringData:
|
|||||||
bootcmd:
|
bootcmd:
|
||||||
- mkdir /mnt/vda
|
- mkdir /mnt/vda
|
||||||
`)
|
`)
|
||||||
|
th.WriteF(filepath.Join(tmpDir.String(), "generateDeployment.sh"), generateDeploymentDotSh)
|
||||||
|
|
||||||
th.WriteF("gener.yaml", `
|
assert.NoError(t, os.Chmod(filepath.Join(tmpDir.String(), "generateDeployment.sh"), 0777))
|
||||||
|
th.WriteF(filepath.Join(tmpDir.String(), "gener.yaml"), `
|
||||||
kind: executable
|
kind: executable
|
||||||
metadata:
|
metadata:
|
||||||
name: demo
|
name: demo
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/function: |
|
config.kubernetes.io/function: |
|
||||||
exec:
|
exec:
|
||||||
path: ./fnplugin_test/fnexectest.sh
|
path: ./generateDeployment.sh
|
||||||
spec:
|
spec:
|
||||||
`)
|
`)
|
||||||
o := th.MakeOptionsPluginsEnabled()
|
|
||||||
o.PluginConfig.FnpLoadingOptions.EnableExec = true
|
m := th.Run(tmpDir.String(), o)
|
||||||
m := th.Run(".", o)
|
assert.NoError(t, err)
|
||||||
th.AssertActualEqualsExpected(m, `
|
yml, err := m.AsYaml()
|
||||||
apiVersion: v1
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, `apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -63,7 +102,6 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/path: deployment_nginx.yaml
|
|
||||||
tshirt-size: small
|
tshirt-size: small
|
||||||
labels:
|
labels:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -80,7 +118,99 @@ spec:
|
|||||||
containers:
|
containers:
|
||||||
- image: nginx
|
- image: nginx
|
||||||
name: nginx
|
name: nginx
|
||||||
|
`, string(yml))
|
||||||
|
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFnExecGeneratorWithOverlay(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsOnDisk()
|
||||||
|
|
||||||
|
th := kusttest_test.MakeHarnessWithFs(t, fSys)
|
||||||
|
o := th.MakeOptionsPluginsEnabled()
|
||||||
|
o.PluginConfig.FnpLoadingOptions.EnableExec = true
|
||||||
|
|
||||||
|
tmpDir, err := filesys.NewTmpConfirmedDir()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
base := filepath.Join(tmpDir.String(), "base")
|
||||||
|
prod := filepath.Join(tmpDir.String(), "prod")
|
||||||
|
assert.NoError(t, fSys.Mkdir(base))
|
||||||
|
assert.NoError(t, fSys.Mkdir(prod))
|
||||||
|
th.WriteK(base, `
|
||||||
|
resources:
|
||||||
|
- short_secret.yaml
|
||||||
|
generators:
|
||||||
|
- gener.yaml
|
||||||
`)
|
`)
|
||||||
|
th.WriteK(prod, `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
`)
|
||||||
|
th.WriteF(filepath.Join(base, "short_secret.yaml"),
|
||||||
|
`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
airshipit.org/ephemeral-user-data: "true"
|
||||||
|
name: node1-bmc-secret
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
userData: |
|
||||||
|
bootcmd:
|
||||||
|
- mkdir /mnt/vda
|
||||||
|
`)
|
||||||
|
th.WriteF(filepath.Join(base, "generateDeployment.sh"), generateDeploymentDotSh)
|
||||||
|
|
||||||
|
assert.NoError(t, os.Chmod(filepath.Join(base, "generateDeployment.sh"), 0777))
|
||||||
|
th.WriteF(filepath.Join(base, "gener.yaml"), `
|
||||||
|
kind: executable
|
||||||
|
metadata:
|
||||||
|
name: demo
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/function: |
|
||||||
|
exec:
|
||||||
|
path: ./generateDeployment.sh
|
||||||
|
spec:
|
||||||
|
`)
|
||||||
|
|
||||||
|
m := th.Run(prod, o)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
yml, err := m.AsYaml()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, `apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
airshipit.org/ephemeral-user-data: "true"
|
||||||
|
name: node1-bmc-secret
|
||||||
|
stringData:
|
||||||
|
userData: |
|
||||||
|
bootcmd:
|
||||||
|
- mkdir /mnt/vda
|
||||||
|
type: Opaque
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
tshirt-size: small
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nginx
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: nginx
|
||||||
|
`, string(yml))
|
||||||
|
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func skipIfNoDocker(t *testing.T) {
|
func skipIfNoDocker(t *testing.T) {
|
||||||
@@ -90,6 +220,7 @@ func skipIfNoDocker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFnContainerGenerator(t *testing.T) {
|
func TestFnContainerGenerator(t *testing.T) {
|
||||||
|
t.Skip("wait for #3881")
|
||||||
skipIfNoDocker(t)
|
skipIfNoDocker(t)
|
||||||
|
|
||||||
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
||||||
@@ -145,8 +276,6 @@ type: Opaque
|
|||||||
apiVersion: policy/v1beta1
|
apiVersion: policy/v1beta1
|
||||||
kind: PodDisruptionBudget
|
kind: PodDisruptionBudget
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: config/demo-budget_poddisruptionbudget.yaml
|
|
||||||
labels:
|
labels:
|
||||||
app: cockroachdb
|
app: cockroachdb
|
||||||
name: demo
|
name: demo
|
||||||
@@ -161,8 +290,6 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: config/demo-public_service.yaml
|
|
||||||
labels:
|
labels:
|
||||||
app: cockroachdb
|
app: cockroachdb
|
||||||
name: demo
|
name: demo
|
||||||
@@ -183,7 +310,6 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/path: config/demo_service.yaml
|
|
||||||
prometheus.io/path: _status/vars
|
prometheus.io/path: _status/vars
|
||||||
prometheus.io/port: "8080"
|
prometheus.io/port: "8080"
|
||||||
prometheus.io/scrape: "true"
|
prometheus.io/scrape: "true"
|
||||||
@@ -208,8 +334,6 @@ spec:
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: StatefulSet
|
kind: StatefulSet
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: config/demo_statefulset.yaml
|
|
||||||
labels:
|
labels:
|
||||||
app: cockroachdb
|
app: cockroachdb
|
||||||
name: demo
|
name: demo
|
||||||
@@ -306,6 +430,7 @@ spec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFnContainerTransformer(t *testing.T) {
|
func TestFnContainerTransformer(t *testing.T) {
|
||||||
|
t.Skip("wait for #3881")
|
||||||
skipIfNoDocker(t)
|
skipIfNoDocker(t)
|
||||||
|
|
||||||
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
// Function plugins should not need the env setup done by MakeEnhancedHarness
|
||||||
@@ -381,7 +506,6 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/path: deployment_nginx.yaml
|
|
||||||
tshirt-size: small
|
tshirt-size: small
|
||||||
labels:
|
labels:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -448,8 +572,6 @@ data:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: namespace_my-namespace.yaml
|
|
||||||
labels:
|
labels:
|
||||||
my-ns-name: function-test
|
my-ns-name: function-test
|
||||||
name: my-namespace
|
name: my-namespace
|
||||||
@@ -457,8 +579,6 @@ metadata:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: namespace_another-namespace.yaml
|
|
||||||
labels:
|
labels:
|
||||||
my-ns-name: function-test
|
my-ns-name: function-test
|
||||||
name: another-namespace
|
name: another-namespace
|
||||||
@@ -506,8 +626,6 @@ data:
|
|||||||
value: value
|
value: value
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/path: configmap_env.yaml
|
|
||||||
name: env
|
name: env
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
cat <<EOF
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
annotations:
|
|
||||||
tshirt-size: small # this injects the resource reservations
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: nginx
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx
|
|
||||||
EOF
|
|
||||||
@@ -81,3 +81,156 @@ helmCharts:
|
|||||||
m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled())
|
m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled())
|
||||||
th.AssertActualEqualsExpected(m, expectedHelm)
|
th.AssertActualEqualsExpected(m, expectedHelm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Last mile helm - show how kustomize puts helm charts into different
|
||||||
|
// namespaces with different customizations.
|
||||||
|
func TestHelmChartProdVsDev(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
|
||||||
|
defer th.Reset()
|
||||||
|
if err := th.ErrIfNoHelm(); err != nil {
|
||||||
|
t.Skip("skipping: " + err.Error())
|
||||||
|
}
|
||||||
|
dirBase := th.MkDir("base")
|
||||||
|
dirProd := th.MkDir("prod")
|
||||||
|
dirDev := th.MkDir("dev")
|
||||||
|
dirBoth := th.MkDir("both")
|
||||||
|
|
||||||
|
th.WriteK(dirBase, `
|
||||||
|
helmCharts:
|
||||||
|
- name: minecraft
|
||||||
|
repo: https://itzg.github.io/minecraft-server-charts
|
||||||
|
version: 3.1.3
|
||||||
|
releaseName: test
|
||||||
|
`)
|
||||||
|
th.WriteK(dirProd, `
|
||||||
|
namespace: prod
|
||||||
|
namePrefix: myProd-
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
`)
|
||||||
|
th.WriteK(dirDev, `
|
||||||
|
namespace: dev
|
||||||
|
namePrefix: myDev-
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
`)
|
||||||
|
th.WriteK(dirBoth, `
|
||||||
|
resources:
|
||||||
|
- ../dev
|
||||||
|
- ../prod
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Base unchanged
|
||||||
|
m := th.Run(dirBase, th.MakeOptionsPluginsEnabled())
|
||||||
|
th.AssertActualEqualsExpected(m, expectedHelm)
|
||||||
|
|
||||||
|
// Prod has a "prod" namespace and a prefix.
|
||||||
|
m = th.Run(dirProd, th.MakeOptionsPluginsEnabled())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
rcon-password: Q0hBTkdFTUUh
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: test-minecraft
|
||||||
|
chart: minecraft-3.1.3
|
||||||
|
heritage: Helm
|
||||||
|
release: test
|
||||||
|
name: myProd-test-minecraft
|
||||||
|
namespace: prod
|
||||||
|
type: Opaque
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: test-minecraft
|
||||||
|
chart: minecraft-3.1.3
|
||||||
|
heritage: Helm
|
||||||
|
release: test
|
||||||
|
name: myProd-test-minecraft
|
||||||
|
namespace: prod
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: minecraft
|
||||||
|
port: 25565
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: minecraft
|
||||||
|
selector:
|
||||||
|
app: test-minecraft
|
||||||
|
type: ClusterIP
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Both has two namespaces.
|
||||||
|
m = th.Run(dirBoth, th.MakeOptionsPluginsEnabled())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
rcon-password: Q0hBTkdFTUUh
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: test-minecraft
|
||||||
|
chart: minecraft-3.1.3
|
||||||
|
heritage: Helm
|
||||||
|
release: test
|
||||||
|
name: myDev-test-minecraft
|
||||||
|
namespace: dev
|
||||||
|
type: Opaque
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: test-minecraft
|
||||||
|
chart: minecraft-3.1.3
|
||||||
|
heritage: Helm
|
||||||
|
release: test
|
||||||
|
name: myDev-test-minecraft
|
||||||
|
namespace: dev
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: minecraft
|
||||||
|
port: 25565
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: minecraft
|
||||||
|
selector:
|
||||||
|
app: test-minecraft
|
||||||
|
type: ClusterIP
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
rcon-password: Q0hBTkdFTUUh
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: test-minecraft
|
||||||
|
chart: minecraft-3.1.3
|
||||||
|
heritage: Helm
|
||||||
|
release: test
|
||||||
|
name: myProd-test-minecraft
|
||||||
|
namespace: prod
|
||||||
|
type: Opaque
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: test-minecraft
|
||||||
|
chart: minecraft-3.1.3
|
||||||
|
heritage: Helm
|
||||||
|
release: test
|
||||||
|
name: myProd-test-minecraft
|
||||||
|
namespace: prod
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: minecraft
|
||||||
|
port: 25565
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: minecraft
|
||||||
|
selector:
|
||||||
|
app: test-minecraft
|
||||||
|
type: ClusterIP
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
124
api/krusty/iampolicygenerator_test.go
Normal file
124
api/krusty/iampolicygenerator_test.go
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package krusty_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGkeGenerator(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeEnhancedHarness(t)
|
||||||
|
defer th.Reset()
|
||||||
|
|
||||||
|
th.WriteK(".", `
|
||||||
|
generators:
|
||||||
|
- |-
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: IAMPolicyGenerator
|
||||||
|
metadata:
|
||||||
|
name: my-gke-generator
|
||||||
|
cloud: gke
|
||||||
|
kubernetesService:
|
||||||
|
name: k8s-sa-name
|
||||||
|
serviceAccount:
|
||||||
|
name: gsa-name
|
||||||
|
projectId: project-id
|
||||||
|
`)
|
||||||
|
expected := `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
iam.gke.io/gcp-service-account: gsa-name@project-id.iam.gserviceaccount.com
|
||||||
|
name: k8s-sa-name
|
||||||
|
`
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGkeGeneratorWithNamespace(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeEnhancedHarness(t)
|
||||||
|
defer th.Reset()
|
||||||
|
|
||||||
|
th.WriteK(".", `
|
||||||
|
generators:
|
||||||
|
- |-
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: IAMPolicyGenerator
|
||||||
|
metadata:
|
||||||
|
name: my-gke-generator
|
||||||
|
cloud: gke
|
||||||
|
kubernetesService:
|
||||||
|
namespace: k8s-namespace
|
||||||
|
name: k8s-sa-name
|
||||||
|
serviceAccount:
|
||||||
|
name: gsa-name
|
||||||
|
projectId: project-id
|
||||||
|
`)
|
||||||
|
expected := `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
iam.gke.io/gcp-service-account: gsa-name@project-id.iam.gserviceaccount.com
|
||||||
|
name: k8s-sa-name
|
||||||
|
namespace: k8s-namespace
|
||||||
|
`
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGkeGeneratorWithTwo(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeEnhancedHarness(t)
|
||||||
|
defer th.Reset()
|
||||||
|
|
||||||
|
th.WriteK(".", `
|
||||||
|
generators:
|
||||||
|
- gkegenerator1.yaml
|
||||||
|
- gkegenerator2.yaml
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteF("gkegenerator1.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: IAMPolicyGenerator
|
||||||
|
metadata:
|
||||||
|
name: my-gke-generator1
|
||||||
|
cloud: gke
|
||||||
|
kubernetesService:
|
||||||
|
namespace: k8s-namespace-1
|
||||||
|
name: k8s-sa-name-1
|
||||||
|
serviceAccount:
|
||||||
|
name: gsa-name-1
|
||||||
|
projectId: project-id-1
|
||||||
|
`)
|
||||||
|
th.WriteF("gkegenerator2.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: IAMPolicyGenerator
|
||||||
|
metadata:
|
||||||
|
name: my-gke-generator2
|
||||||
|
cloud: gke
|
||||||
|
kubernetesService:
|
||||||
|
name: k8s-sa-name-2
|
||||||
|
serviceAccount:
|
||||||
|
name: gsa-name-2
|
||||||
|
projectId: project-id-2
|
||||||
|
`)
|
||||||
|
expected := `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
iam.gke.io/gcp-service-account: gsa-name-1@project-id-1.iam.gserviceaccount.com
|
||||||
|
name: k8s-sa-name-1
|
||||||
|
namespace: k8s-namespace-1
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
iam.gke.io/gcp-service-account: gsa-name-2@project-id-2.iam.gserviceaccount.com
|
||||||
|
name: k8s-sa-name-2
|
||||||
|
`
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, expected)
|
||||||
|
}
|
||||||
@@ -230,3 +230,92 @@ spec:
|
|||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPathWithCronJobV1(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteK(".", `
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- resources.yaml
|
||||||
|
patches:
|
||||||
|
- patch: |
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: test
|
||||||
|
env:
|
||||||
|
- name: ENV_NEW
|
||||||
|
value: val_new
|
||||||
|
target:
|
||||||
|
kind: CronJob
|
||||||
|
name: test
|
||||||
|
`)
|
||||||
|
th.WriteF("resources.yaml", `
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
schedule: "5 10 * * 1"
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
backoffLimit: 3
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
containers:
|
||||||
|
- name: test
|
||||||
|
image: bash
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- echo "test"
|
||||||
|
env:
|
||||||
|
- name: ENV1
|
||||||
|
value: val1
|
||||||
|
- name: ENV2
|
||||||
|
value: val2
|
||||||
|
- name: ENV3
|
||||||
|
value: val3`)
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
backoffLimit: 3
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- echo "test"
|
||||||
|
env:
|
||||||
|
- name: ENV_NEW
|
||||||
|
value: val_new
|
||||||
|
- name: ENV1
|
||||||
|
value: val1
|
||||||
|
- name: ENV2
|
||||||
|
value: val2
|
||||||
|
- name: ENV3
|
||||||
|
value: val3
|
||||||
|
image: bash
|
||||||
|
name: test
|
||||||
|
restartPolicy: Never
|
||||||
|
schedule: 5 10 * * 1
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/builtins"
|
"sigs.k8s.io/kustomize/api/builtins"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||||
"sigs.k8s.io/kustomize/api/internal/target"
|
"sigs.k8s.io/kustomize/api/internal/target"
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
@@ -17,6 +16,7 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/provider"
|
"sigs.k8s.io/kustomize/api/provider"
|
||||||
"sigs.k8s.io/kustomize/api/resmap"
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -90,19 +90,25 @@ func (b *Kustomizer) Run(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if b.options.DoLegacyResourceSort {
|
if b.options.DoLegacyResourceSort {
|
||||||
builtins.NewLegacyOrderTransformerPlugin().Transform(m)
|
err = builtins.NewLegacyOrderTransformerPlugin().Transform(m)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if b.options.AddManagedbyLabel {
|
if b.options.AddManagedbyLabel {
|
||||||
t := builtins.LabelTransformerPlugin{
|
t := builtins.LabelTransformerPlugin{
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
konfig.ManagedbyLabelKey: fmt.Sprintf(
|
konfig.ManagedbyLabelKey: fmt.Sprintf("kustomize-%s", provenance.GetProvenance().Semver()),
|
||||||
"kustomize-%s", provenance.GetProvenance().Semver())},
|
},
|
||||||
FieldSpecs: []types.FieldSpec{{
|
FieldSpecs: []types.FieldSpec{{
|
||||||
Path: "metadata/labels",
|
Path: "metadata/labels",
|
||||||
CreateIfNotPresent: true,
|
CreateIfNotPresent: true,
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
t.Transform(m)
|
err = t.Transform(m)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m.RemoveBuildAnnotations()
|
m.RemoveBuildAnnotations()
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/krusty"
|
"sigs.k8s.io/kustomize/api/krusty"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A simple usage example to shows what happens when
|
// A simple usage example to shows what happens when
|
||||||
|
|||||||
@@ -6,9 +6,319 @@ package krusty_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestPatchesInOneFile(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteK("base", `
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- deployment-controller-manager.yaml
|
||||||
|
- deployment-audit-manager.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("base/namespace.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
admission.gatekeeper.sh/ignore: no-self-managing
|
||||||
|
name: system
|
||||||
|
`)
|
||||||
|
th.WriteF("base/deployment-controller-manager.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
gatekeeper.sh/operation: webhook
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
gatekeeper.sh/operation: webhook
|
||||||
|
replicas: 3
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
container.seccomp.security.alpha.kubernetes.io/manager: runtime/default
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
gatekeeper.sh/operation: webhook
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- /manager
|
||||||
|
args:
|
||||||
|
- "--port=8443"
|
||||||
|
- "--logtostderr"
|
||||||
|
- "--exempt-namespace=gatekeeper-system"
|
||||||
|
- "--operation=webhook"
|
||||||
|
image: openpolicyagent/gatekeeper:v3.4.0
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: manager
|
||||||
|
terminationGracePeriodSeconds: 60
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/os: linux
|
||||||
|
priorityClassName: system-cluster-critical
|
||||||
|
`)
|
||||||
|
th.WriteF("base/deployment-audit-manager.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: audit
|
||||||
|
namespace: system
|
||||||
|
labels:
|
||||||
|
control-plane: audit-controller
|
||||||
|
gatekeeper.sh/operation: audit
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
control-plane: audit-controller
|
||||||
|
gatekeeper.sh/operation: audit
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: audit-controller
|
||||||
|
gatekeeper.sh/operation: audit
|
||||||
|
annotations:
|
||||||
|
container.seccomp.security.alpha.kubernetes.io/manager: runtime/default
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: true
|
||||||
|
containers:
|
||||||
|
- args:
|
||||||
|
- --operation=audit
|
||||||
|
- --operation=status
|
||||||
|
- --logtostderr
|
||||||
|
command:
|
||||||
|
- /manager
|
||||||
|
env:
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
image: openpolicyagent/gatekeeper:v3.4.0
|
||||||
|
imagePullPolicy: Always
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 9090
|
||||||
|
name: manager
|
||||||
|
serviceAccountName: gatekeeper-admin
|
||||||
|
terminationGracePeriodSeconds: 60
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/os: linux
|
||||||
|
priorityClassName: system-cluster-critical
|
||||||
|
`)
|
||||||
|
const imagePatchAuditManager = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: audit
|
||||||
|
namespace: system
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: AUDIT_IMAGE
|
||||||
|
name: manager
|
||||||
|
args:
|
||||||
|
- --port=8443
|
||||||
|
- --logtostderr
|
||||||
|
- --emit-admission-events
|
||||||
|
- --exempt-namespace=gatekeeper-system
|
||||||
|
- --operation=webhook
|
||||||
|
- --disable-opa-builtin=http.send
|
||||||
|
`
|
||||||
|
const imagePatchControllerManager = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: CONTROLLER_IMAGE
|
||||||
|
name: manager
|
||||||
|
args:
|
||||||
|
- --emit-audit-events
|
||||||
|
- --operation=audit
|
||||||
|
- --operation=status
|
||||||
|
- --logtostderr
|
||||||
|
`
|
||||||
|
th.WriteF(
|
||||||
|
"overlay/image_patch_audit_manager.yaml",
|
||||||
|
imagePatchAuditManager)
|
||||||
|
th.WriteF(
|
||||||
|
"overlay/image_patch_controller_manager.yaml",
|
||||||
|
imagePatchControllerManager)
|
||||||
|
const expected = `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
admission.gatekeeper.sh/ignore: no-self-managing
|
||||||
|
control-plane: controller-manager
|
||||||
|
name: system
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
gatekeeper.sh/operation: webhook
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
gatekeeper.sh/operation: webhook
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
container.seccomp.security.alpha.kubernetes.io/manager: runtime/default
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
gatekeeper.sh/operation: webhook
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- args:
|
||||||
|
- --emit-audit-events
|
||||||
|
- --operation=audit
|
||||||
|
- --operation=status
|
||||||
|
- --logtostderr
|
||||||
|
command:
|
||||||
|
- /manager
|
||||||
|
image: CONTROLLER_IMAGE
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: manager
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/os: linux
|
||||||
|
priorityClassName: system-cluster-critical
|
||||||
|
terminationGracePeriodSeconds: 60
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: audit-controller
|
||||||
|
gatekeeper.sh/operation: audit
|
||||||
|
name: audit
|
||||||
|
namespace: system
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
control-plane: audit-controller
|
||||||
|
gatekeeper.sh/operation: audit
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
container.seccomp.security.alpha.kubernetes.io/manager: runtime/default
|
||||||
|
labels:
|
||||||
|
control-plane: audit-controller
|
||||||
|
gatekeeper.sh/operation: audit
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: true
|
||||||
|
containers:
|
||||||
|
- args:
|
||||||
|
- --port=8443
|
||||||
|
- --logtostderr
|
||||||
|
- --emit-admission-events
|
||||||
|
- --exempt-namespace=gatekeeper-system
|
||||||
|
- --operation=webhook
|
||||||
|
- --disable-opa-builtin=http.send
|
||||||
|
command:
|
||||||
|
- /manager
|
||||||
|
env:
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
image: AUDIT_IMAGE
|
||||||
|
imagePullPolicy: Always
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 9090
|
||||||
|
name: manager
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/os: linux
|
||||||
|
priorityClassName: system-cluster-critical
|
||||||
|
serviceAccountName: gatekeeper-admin
|
||||||
|
terminationGracePeriodSeconds: 60
|
||||||
|
`
|
||||||
|
// Technique 1: "patchesStrategicMerge:" field, two patch files.
|
||||||
|
th.WriteK("overlay", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- image_patch_controller_manager.yaml
|
||||||
|
- image_patch_audit_manager.yaml
|
||||||
|
`)
|
||||||
|
m := th.Run("overlay", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, expected)
|
||||||
|
|
||||||
|
// Technique 2: "patches:" field, two patch files.
|
||||||
|
th.WriteK("overlay", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
patches:
|
||||||
|
- path: image_patch_controller_manager.yaml
|
||||||
|
- path: image_patch_audit_manager.yaml
|
||||||
|
`)
|
||||||
|
m = th.Run("overlay", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, expected)
|
||||||
|
|
||||||
|
// Technique 3: "patchesStrategicMerge:" field, one patch file.
|
||||||
|
th.WriteK("overlay", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- twoPatchesInOneFile.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF(
|
||||||
|
"overlay/twoPatchesInOneFile.yaml",
|
||||||
|
imagePatchAuditManager+"\n---\n"+imagePatchControllerManager)
|
||||||
|
m = th.Run("overlay", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, expected)
|
||||||
|
|
||||||
|
// Technique 4: "patches:" field, one patch file. Fails.
|
||||||
|
th.WriteK("overlay", `
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
patches:
|
||||||
|
- path: twoPatchesInOneFile.yaml
|
||||||
|
`)
|
||||||
|
err := th.RunWithErr("overlay", th.MakeDefaultOptions())
|
||||||
|
assert.Error(t, err)
|
||||||
|
// This should fail, because the semantics of the `patches` field.
|
||||||
|
// That field allows specific patch targeting to a list of targets,
|
||||||
|
// while the `patchesStrategicMerge` field accepts patches that
|
||||||
|
// implicitly identify their targets via GVKN.
|
||||||
|
assert.Contains(t, err.Error(), "unable to parse SM or JSON patch from ")
|
||||||
|
}
|
||||||
|
|
||||||
func TestRemoveEmptyDirWithNullFieldInSmp(t *testing.T) {
|
func TestRemoveEmptyDirWithNullFieldInSmp(t *testing.T) {
|
||||||
th := kusttest_test.MakeHarness(t)
|
th := kusttest_test.MakeHarness(t)
|
||||||
th.WriteK(".", `
|
th.WriteK(".", `
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ func writeTestSchema(th kusttest_test.Harness, filepath string) {
|
|||||||
th.WriteF(filepath+"mycrd_schema.json", string(bytes))
|
th.WriteF(filepath+"mycrd_schema.json", string(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeTestSchemaYaml(th kusttest_test.Harness, filepath string) {
|
||||||
|
bytes, _ := ioutil.ReadFile("testdata/customschema.yaml")
|
||||||
|
th.WriteF(filepath+"mycrd_schema.yaml", string(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
func writeCustomResource(th kusttest_test.Harness, filepath string) {
|
func writeCustomResource(th kusttest_test.Harness, filepath string) {
|
||||||
th.WriteF(filepath, `
|
th.WriteF(filepath, `
|
||||||
apiVersion: example.com/v1alpha1
|
apiVersion: example.com/v1alpha1
|
||||||
@@ -103,6 +108,21 @@ openapi:
|
|||||||
th.AssertActualEqualsExpected(m, patchedCustomResource)
|
th.AssertActualEqualsExpected(m, patchedCustomResource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCustomOpenApiFieldYaml(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteK(".", `
|
||||||
|
resources:
|
||||||
|
- mycrd.yaml
|
||||||
|
openapi:
|
||||||
|
path: mycrd_schema.yaml
|
||||||
|
`+customSchemaPatch)
|
||||||
|
writeCustomResource(th, "mycrd.yaml")
|
||||||
|
writeTestSchemaYaml(th, "./")
|
||||||
|
openapi.ResetOpenAPI()
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, patchedCustomResource)
|
||||||
|
}
|
||||||
|
|
||||||
// Error if user tries to specify both builtin version
|
// Error if user tries to specify both builtin version
|
||||||
// and custom schema
|
// and custom schema
|
||||||
func TestCustomOpenApiFieldBothPathAndVersion(t *testing.T) {
|
func TestCustomOpenApiFieldBothPathAndVersion(t *testing.T) {
|
||||||
@@ -111,7 +131,7 @@ func TestCustomOpenApiFieldBothPathAndVersion(t *testing.T) {
|
|||||||
resources:
|
resources:
|
||||||
- mycrd.yaml
|
- mycrd.yaml
|
||||||
openapi:
|
openapi:
|
||||||
version: v1.20.4
|
version: v1.21.2
|
||||||
path: mycrd_schema.json
|
path: mycrd_schema.json
|
||||||
`+customSchemaPatch)
|
`+customSchemaPatch)
|
||||||
writeCustomResource(th, "mycrd.yaml")
|
writeCustomResource(th, "mycrd.yaml")
|
||||||
@@ -197,7 +217,7 @@ openapi:
|
|||||||
resources:
|
resources:
|
||||||
- ../base
|
- ../base
|
||||||
openapi:
|
openapi:
|
||||||
version: v1.20.4
|
version: v1.21.2
|
||||||
`+customSchemaPatch)
|
`+customSchemaPatch)
|
||||||
writeCustomResource(th, "base/mycrd.yaml")
|
writeCustomResource(th, "base/mycrd.yaml")
|
||||||
writeTestSchema(th, "base/")
|
writeTestSchema(th, "base/")
|
||||||
@@ -215,7 +235,7 @@ spec:
|
|||||||
- image: nginx
|
- image: nginx
|
||||||
name: server
|
name: server
|
||||||
`)
|
`)
|
||||||
assert.Equal(t, "v1204", openapi.GetSchemaVersion())
|
assert.Equal(t, "v1212", openapi.GetSchemaVersion())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCustomOpenAPIFieldFromComponent(t *testing.T) {
|
func TestCustomOpenAPIFieldFromComponent(t *testing.T) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func TestOpenApiFieldBasicUsage(t *testing.T) {
|
|||||||
th := kusttest_test.MakeHarness(t)
|
th := kusttest_test.MakeHarness(t)
|
||||||
th.WriteK(".", `
|
th.WriteK(".", `
|
||||||
openapi:
|
openapi:
|
||||||
version: v1.20.4
|
version: v1.21.2
|
||||||
resources:
|
resources:
|
||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
`)
|
`)
|
||||||
@@ -44,7 +44,8 @@ spec:
|
|||||||
containers:
|
containers:
|
||||||
- image: whatever
|
- image: whatever
|
||||||
`)
|
`)
|
||||||
assert.Equal(t, "v1204", openapi.GetSchemaVersion())
|
assert.Equal(t, "v1212", openapi.GetSchemaVersion())
|
||||||
|
openapi.ResetOpenAPI()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOpenApiFieldNotBuiltin(t *testing.T) {
|
func TestOpenApiFieldNotBuiltin(t *testing.T) {
|
||||||
@@ -71,6 +72,7 @@ spec:
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected an error")
|
t.Fatalf("expected an error")
|
||||||
}
|
}
|
||||||
|
openapi.ResetOpenAPI()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOpenApiFieldDefaultVersion(t *testing.T) {
|
func TestOpenApiFieldDefaultVersion(t *testing.T) {
|
||||||
@@ -104,4 +106,5 @@ spec:
|
|||||||
- image: whatever
|
- image: whatever
|
||||||
`)
|
`)
|
||||||
assert.Equal(t, kubernetesapi.DefaultOpenAPI, openapi.GetSchemaVersion())
|
assert.Equal(t, kubernetesapi.DefaultOpenAPI, openapi.GetSchemaVersion())
|
||||||
|
openapi.ResetOpenAPI()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The PrintPluginEnv plugin is a toy plugin that emits
|
// The PrintPluginEnv plugin is a toy plugin that emits
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
package krusty_test
|
package krusty_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/internal/utils"
|
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||||
"sigs.k8s.io/kustomize/api/krusty"
|
"sigs.k8s.io/kustomize/api/krusty"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRemoteLoad(t *testing.T) {
|
func TestRemoteLoad(t *testing.T) {
|
||||||
@@ -39,3 +40,124 @@ spec:
|
|||||||
name: nginx
|
name: nginx
|
||||||
`, string(yml))
|
`, string(yml))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoteResource(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsOnDisk()
|
||||||
|
b := krusty.MakeKustomizer(krusty.MakeDefaultOptions())
|
||||||
|
tmpDir, err := filesys.NewTmpConfirmedDir()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "kustomization.yaml"), []byte(`
|
||||||
|
resources:
|
||||||
|
- github.com/kubernetes-sigs/kustomize/examples/multibases/dev/?ref=v1.0.6
|
||||||
|
`)))
|
||||||
|
m, err := b.Run(
|
||||||
|
fSys,
|
||||||
|
tmpDir.String())
|
||||||
|
if utils.IsErrTimeout(err) {
|
||||||
|
// Don't fail on timeouts.
|
||||||
|
t.SkipNow()
|
||||||
|
}
|
||||||
|
assert.NoError(t, err)
|
||||||
|
yml, err := m.AsYaml()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: myapp
|
||||||
|
name: dev-myapp-pod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx
|
||||||
|
`, string(yml))
|
||||||
|
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoteResourceAnnoOrigin(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsOnDisk()
|
||||||
|
b := krusty.MakeKustomizer(krusty.MakeDefaultOptions())
|
||||||
|
tmpDir, err := filesys.NewTmpConfirmedDir()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "kustomization.yaml"), []byte(`
|
||||||
|
resources:
|
||||||
|
- github.com/kubernetes-sigs/kustomize/examples/multibases/dev/?ref=v1.0.6
|
||||||
|
buildMetadata: [originAnnotations]
|
||||||
|
`)))
|
||||||
|
m, err := b.Run(
|
||||||
|
fSys,
|
||||||
|
tmpDir.String())
|
||||||
|
if utils.IsErrTimeout(err) {
|
||||||
|
// Don't fail on timeouts.
|
||||||
|
t.SkipNow()
|
||||||
|
}
|
||||||
|
assert.NoError(t, err)
|
||||||
|
yml, err := m.AsYaml()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/origin: |
|
||||||
|
path: examples/multibases/base/pod.yaml
|
||||||
|
repo: https://github.com/kubernetes-sigs/kustomize
|
||||||
|
ref: v1.0.6
|
||||||
|
labels:
|
||||||
|
app: myapp
|
||||||
|
name: dev-myapp-pod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx
|
||||||
|
`, string(yml))
|
||||||
|
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoteResourceAsBaseWithAnnoOrigin(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsOnDisk()
|
||||||
|
b := krusty.MakeKustomizer(krusty.MakeDefaultOptions())
|
||||||
|
tmpDir, err := filesys.NewTmpConfirmedDir()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
base := filepath.Join(tmpDir.String(), "base")
|
||||||
|
prod := filepath.Join(tmpDir.String(), "prod")
|
||||||
|
assert.NoError(t, fSys.Mkdir(base))
|
||||||
|
assert.NoError(t, fSys.Mkdir(prod))
|
||||||
|
assert.NoError(t, fSys.WriteFile(filepath.Join(base, "kustomization.yaml"), []byte(`
|
||||||
|
resources:
|
||||||
|
- github.com/kubernetes-sigs/kustomize/examples/multibases/dev/?ref=v1.0.6
|
||||||
|
`)))
|
||||||
|
assert.NoError(t, fSys.WriteFile(filepath.Join(prod, "kustomization.yaml"), []byte(`
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
namePrefix: prefix-
|
||||||
|
buildMetadata: [originAnnotations]
|
||||||
|
`)))
|
||||||
|
|
||||||
|
m, err := b.Run(
|
||||||
|
fSys,
|
||||||
|
prod)
|
||||||
|
if utils.IsErrTimeout(err) {
|
||||||
|
// Don't fail on timeouts.
|
||||||
|
t.SkipNow()
|
||||||
|
}
|
||||||
|
assert.NoError(t, err)
|
||||||
|
yml, err := m.AsYaml()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/origin: |
|
||||||
|
path: examples/multibases/base/pod.yaml
|
||||||
|
repo: https://github.com/kubernetes-sigs/kustomize
|
||||||
|
ref: v1.0.6
|
||||||
|
labels:
|
||||||
|
app: myapp
|
||||||
|
name: prefix-dev-myapp-pod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx
|
||||||
|
`, string(yml))
|
||||||
|
assert.NoError(t, fSys.RemoveAll(tmpDir.String()))
|
||||||
|
}
|
||||||
|
|||||||
@@ -261,3 +261,224 @@ spec:
|
|||||||
name: nginx
|
name: nginx
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReplacementTransformerWithOriginalName(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeEnhancedHarness(t)
|
||||||
|
defer th.Reset()
|
||||||
|
|
||||||
|
th.WriteF("base/deployments.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: target
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:oldtag
|
||||||
|
name: nginx
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: source
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:newtag
|
||||||
|
name: nginx
|
||||||
|
`)
|
||||||
|
th.WriteK("base", `
|
||||||
|
resources:
|
||||||
|
- deployments.yaml
|
||||||
|
`)
|
||||||
|
th.WriteK("overlay", `
|
||||||
|
namePrefix: prefix1-
|
||||||
|
resources:
|
||||||
|
- ../base
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteK(".", `
|
||||||
|
namePrefix: prefix2-
|
||||||
|
resources:
|
||||||
|
- overlay
|
||||||
|
replacements:
|
||||||
|
- path: replacement.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("replacement.yaml", `
|
||||||
|
source:
|
||||||
|
name: source
|
||||||
|
fieldPath: spec.template.spec.containers.0.image
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
name: prefix1-target
|
||||||
|
fieldPaths:
|
||||||
|
- spec.template.spec.containers.[name=nginx].image
|
||||||
|
`)
|
||||||
|
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: prefix2-prefix1-target
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:newtag
|
||||||
|
name: nginx
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: prefix2-prefix1-source
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:newtag
|
||||||
|
name: nginx
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Address namePrefix in overlay not applying to replacement targets
|
||||||
|
// The property `data.blue-name` should end up being `overlay-blue` instead of `blue`
|
||||||
|
// https://github.com/kubernetes-sigs/kustomize/issues/4034
|
||||||
|
func TestReplacementTransformerWithNamePrefixOverlay(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeEnhancedHarness(t)
|
||||||
|
defer th.Reset()
|
||||||
|
|
||||||
|
th.WriteK("base", `
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
configMapGenerator:
|
||||||
|
- name: blue
|
||||||
|
- name: red
|
||||||
|
replacements:
|
||||||
|
- source:
|
||||||
|
kind: ConfigMap
|
||||||
|
name: blue
|
||||||
|
fieldPath: metadata.name
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
name: red
|
||||||
|
fieldPaths:
|
||||||
|
- data.blue-name
|
||||||
|
options:
|
||||||
|
create: true
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteK(".", `
|
||||||
|
namePrefix: overlay-
|
||||||
|
resources:
|
||||||
|
- base
|
||||||
|
`)
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: overlay-blue
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
blue-name: blue
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: overlay-red
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Address namespace in overlay not applying to replacement targets
|
||||||
|
// The property `data.blue-namespace` should end up being `overlay-namespace` instead of `base-namespace`
|
||||||
|
// https://github.com/kubernetes-sigs/kustomize/issues/4034
|
||||||
|
func TestReplacementTransformerWithNamespaceOverlay(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeEnhancedHarness(t)
|
||||||
|
defer th.Reset()
|
||||||
|
|
||||||
|
th.WriteK("base", `
|
||||||
|
namespace: base-namespace
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
configMapGenerator:
|
||||||
|
- name: blue
|
||||||
|
- name: red
|
||||||
|
replacements:
|
||||||
|
- source:
|
||||||
|
kind: ConfigMap
|
||||||
|
name: blue
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
name: red
|
||||||
|
fieldPaths:
|
||||||
|
- data.blue-namespace
|
||||||
|
options:
|
||||||
|
create: true
|
||||||
|
`)
|
||||||
|
|
||||||
|
th.WriteK(".", `
|
||||||
|
namespace: overlay-namespace
|
||||||
|
resources:
|
||||||
|
- base
|
||||||
|
`)
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: blue
|
||||||
|
namespace: overlay-namespace
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
blue-namespace: base-namespace
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: red
|
||||||
|
namespace: overlay-namespace
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Address configMapGenerator suffix not applying to replacement targets
|
||||||
|
// The property `data.blue-name` should end up being `blue-6ct58987ht` instead of `blue`
|
||||||
|
// https://github.com/kubernetes-sigs/kustomize/issues/4034
|
||||||
|
func TestReplacementTransformerWithConfigMapGenerator(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeEnhancedHarness(t)
|
||||||
|
defer th.Reset()
|
||||||
|
|
||||||
|
th.WriteK(".", `
|
||||||
|
configMapGenerator:
|
||||||
|
- name: blue
|
||||||
|
- name: red
|
||||||
|
replacements:
|
||||||
|
- source:
|
||||||
|
kind: ConfigMap
|
||||||
|
name: blue
|
||||||
|
fieldPath: metadata.name
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
name: red
|
||||||
|
fieldPaths:
|
||||||
|
- data.blue-name
|
||||||
|
options:
|
||||||
|
create: true
|
||||||
|
`)
|
||||||
|
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: blue-6ct58987ht
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
blue-name: blue
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: red-dc6gc5btkc
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
75
api/krusty/testdata/customschema.yaml
vendored
Normal file
75
api/krusty/testdata/customschema.yaml
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
definitions:
|
||||||
|
v1alpha1.MyCRD:
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
properties:
|
||||||
|
template:
|
||||||
|
"$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec"
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
properties:
|
||||||
|
success:
|
||||||
|
type: boolean
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
x-kubernetes-group-version-kind:
|
||||||
|
- group: example.com
|
||||||
|
kind: MyCRD
|
||||||
|
version: v1alpha1
|
||||||
|
io.k8s.api.core.v1.PodTemplateSpec:
|
||||||
|
properties:
|
||||||
|
metadata:
|
||||||
|
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
|
||||||
|
spec:
|
||||||
|
"$ref": "#/definitions/io.k8s.api.core.v1.PodSpec"
|
||||||
|
type: object
|
||||||
|
io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta:
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
io.k8s.api.core.v1.PodSpec:
|
||||||
|
properties:
|
||||||
|
containers:
|
||||||
|
items:
|
||||||
|
"$ref": "#/definitions/io.k8s.api.core.v1.Container"
|
||||||
|
type: array
|
||||||
|
x-kubernetes-patch-merge-key: name
|
||||||
|
x-kubernetes-patch-strategy: merge
|
||||||
|
type: object
|
||||||
|
io.k8s.api.core.v1.Container:
|
||||||
|
properties:
|
||||||
|
command:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
image:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
ports:
|
||||||
|
items:
|
||||||
|
"$ref": "#/definitions/io.k8s.api.core.v1.ContainerPort"
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- containerPort
|
||||||
|
- protocol
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
x-kubernetes-patch-merge-key: containerPort
|
||||||
|
x-kubernetes-patch-strategy: merge
|
||||||
|
type: object
|
||||||
|
io.k8s.api.core.v1.ContainerPort:
|
||||||
|
properties:
|
||||||
|
containerPort:
|
||||||
|
type: integer
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
protocol:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
@@ -7,10 +7,11 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"github.com/stretchr/testify/require"
|
||||||
ldr "sigs.k8s.io/kustomize/api/loader"
|
ldr "sigs.k8s.io/kustomize/api/loader"
|
||||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeKvLoader(fSys filesys.FileSystem) *loader {
|
func makeKvLoader(fSys filesys.FileSystem) *loader {
|
||||||
@@ -83,7 +84,8 @@ func TestKeyValuesFromFileSources(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fSys := filesys.MakeFsInMemory()
|
fSys := filesys.MakeFsInMemory()
|
||||||
fSys.WriteFile("/files/app-init.ini", []byte("FOO=bar"))
|
err := fSys.WriteFile("/files/app-init.ini", []byte("FOO=bar"))
|
||||||
|
require.NoError(t, err)
|
||||||
kvl := makeKvLoader(fSys)
|
kvl := makeKvLoader(fSys)
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
kvs, err := kvl.keyValuesFromFileSources(tc.sources)
|
kvs, err := kvl.keyValuesFromFileSources(tc.sources)
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/api/internal/git"
|
"sigs.k8s.io/kustomize/api/internal/git"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fileLoader is a kustomization's interface to files.
|
// fileLoader is a kustomization's interface to files.
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/api/internal/git"
|
"sigs.k8s.io/kustomize/api/internal/git"
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testData struct {
|
type testData struct {
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
package loader
|
package loader
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
|
||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/api/internal/git"
|
"sigs.k8s.io/kustomize/api/internal/git"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewLoader returns a Loader pointed at the given target.
|
// NewLoader returns a Loader pointed at the given target.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ package loader
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LoadRestrictorFunc func(
|
type LoadRestrictorFunc func(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRestrictionNone(t *testing.T) {
|
func TestRestrictionNone(t *testing.T) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user