mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-29 17:41:13 +00:00
Compare commits
163 Commits
api/v0.8.1
...
kustomize/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63ec6bdb3d | ||
|
|
25bfe6f306 | ||
|
|
febfaf16dc | ||
|
|
8268b17700 | ||
|
|
0889995a61 | ||
|
|
4e476ae574 | ||
|
|
7efd7d23fe | ||
|
|
6fb944815b | ||
|
|
5e3432fbbe | ||
|
|
f0c6bd7773 | ||
|
|
dd579c905d | ||
|
|
22b735885a | ||
|
|
b7c5058e37 | ||
|
|
baff5f4359 | ||
|
|
dce4ea5846 | ||
|
|
c47fc48607 | ||
|
|
1d9b6cbe57 | ||
|
|
1cb93123fc | ||
|
|
c6cb42ec27 | ||
|
|
67a5f6d68f | ||
|
|
e997cc5486 | ||
|
|
53577a5190 | ||
|
|
c1ae234a64 | ||
|
|
02cb395ec2 | ||
|
|
65e7529ca0 | ||
|
|
f70743b267 | ||
|
|
f4382738ab | ||
|
|
a100dca303 | ||
|
|
50414208d1 | ||
|
|
e17a007719 | ||
|
|
dd3c5f5c0a | ||
|
|
fb3f560e0c | ||
|
|
12c177a365 | ||
|
|
402f6ca72b | ||
|
|
2b8a39373e | ||
|
|
17f18604e4 | ||
|
|
99e404cb61 | ||
|
|
d4e3b4f832 | ||
|
|
6552b90657 | ||
|
|
bf57d698b1 | ||
|
|
4d002af735 | ||
|
|
2bfc7cc1b0 | ||
|
|
0244f0919e | ||
|
|
f122fb12f3 | ||
|
|
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 | ||
|
|
02d14d724a | ||
|
|
78737f5a38 |
@@ -1,6 +1,25 @@
|
|||||||
|
[SIG-CLI]: https://github.com/kubernetes/community/tree/master/sig-cli
|
||||||
|
[Slack channel]: https://kubernetes.slack.com/messages/kustomize
|
||||||
|
[Mailing list]: https://groups.google.com/forum/#!forum/kubernetes-sig-cli
|
||||||
|
|
||||||
|
[OWNERS file spec]: https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md
|
||||||
|
[Kustomize OWNERS_ALIASES]: https://github.com/kubernetes-sigs/kustomize/blob/8049f7b1af52e8a7ec26faf6cf714f560d0043c5/OWNERS_ALIASES
|
||||||
|
[SIG-CLI Teams]: https://github.com/kubernetes/org/blob/main/config/kubernetes-sigs/sig-cli/teams.yaml
|
||||||
|
[Github permissions]: https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization#repository-access-for-each-permission-level
|
||||||
|
|
||||||
|
[Contributor License Agreement]: https://git.k8s.io/community/CLA.md
|
||||||
|
[Kubernetes Contributor Guide]: http://git.k8s.io/community/contributors/guide
|
||||||
|
[Contributor Cheat Sheet]: https://git.k8s.io/community/contributors/guide/contributor-cheatsheet/README.md
|
||||||
|
[CNCF Code of Conduct]: https://github.com/cncf/foundation/blob/master/code-of-conduct.md
|
||||||
|
[Kubernetes Community Membership]: https://github.com/kubernetes/community/blob/master/community-membership.md
|
||||||
|
|
||||||
|
[Contribution Guide]: https://kubectl.docs.kubernetes.io/contributing/kustomize/
|
||||||
|
[MacOS Dev Guide]: https://kubectl.docs.kubernetes.io/contributing/kustomize/mac/
|
||||||
|
[Windows Dev Guide]: https://kubectl.docs.kubernetes.io/contributing/kustomize/windows/
|
||||||
|
|
||||||
# Contributing Guidelines
|
# Contributing Guidelines
|
||||||
|
|
||||||
Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt:
|
Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the [CNCF Code of Conduct]. Here is an excerpt:
|
||||||
|
|
||||||
_As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._
|
_As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._
|
||||||
|
|
||||||
@@ -8,13 +27,22 @@ _As contributors and maintainers of this project, and in the interest of fosteri
|
|||||||
|
|
||||||
Dev guides:
|
Dev guides:
|
||||||
|
|
||||||
- [Mac](docs/macDevGuide.md)
|
- [Contribution Guide]
|
||||||
|
- [MacOS Dev Guide]
|
||||||
|
- [Windows Dev Guide]
|
||||||
|
|
||||||
We have full documentation on how to get started contributing here:
|
General resources for contributors:
|
||||||
|
|
||||||
- [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests
|
- [Contributor License Agreement] - Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests.
|
||||||
- [Kubernetes Contributor Guide](http://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](http://git.k8s.io/community/contributors/guide#contributing)
|
- [Kubernetes Contributor Guide] - Main contributor documentation.
|
||||||
- [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet/README.md) - Common resources for existing developers
|
- [Contributor Cheat Sheet] - Common resources for existing developers.
|
||||||
|
|
||||||
|
Here are some additional ideas to help you get started with Kustomize:
|
||||||
|
- Attend a Kustomize Bug Scrub. Check the [SIG-CLI] meetings list to find the next one.
|
||||||
|
- Help triage issues by confirming validity and applying the appropriate `kind` label (e.g. comment `/kind bug`).
|
||||||
|
- Pick up an issue to fix. Issues with the `help-wanted` label are a good place to start, but you can also look for any issue with the `triage/accepted` label and no assignee. Remember to `/assign` yourself to let others know you're working on it.
|
||||||
|
- Help confirm new issues labelled `kind/bug` by reproducing them with the latest release.
|
||||||
|
- Support Kustomize users by responding to questions on issues labelled `kind/support` or in the [Slack channel].
|
||||||
|
|
||||||
## Mentorship
|
## Mentorship
|
||||||
|
|
||||||
@@ -22,19 +50,22 @@ We have full documentation on how to get started contributing here:
|
|||||||
|
|
||||||
## Contributor Ladder
|
## 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:
|
Kustomize follows the [Kubernetes Community Membership] 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. Contributor: Anyone who actively contributes code, issues or reviews to the project. All contributors must sign the [Contributor License Agreement].
|
||||||
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. Reviewer: Contributors with a history of review and authorship on Kustomize. Has LGTM rights on the Kustomize repo (as do all kubernetes-sigs org members). Active contributors are encouraged to join the reviewers list to be automatically pinged on PRs.
|
||||||
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. Approver: Highly experienced active reviewer and contributor to Kustomize. Has both LTGM and approval rights on the Kustomize repo, as well as "maintain" [Github permissions].
|
||||||
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).
|
1. Owner: Approver 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 "admin" [Github permissions].
|
||||||
|
|
||||||
|
The kyaml module within the Kustomize repo has additional owners following the same ladder.
|
||||||
|
|
||||||
Administrative notes:
|
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).
|
- The [OWNERS file spec] is a useful resources in making changes.
|
||||||
|
- Maintainers and admins must be added to the appropriate lists in both [Kustomize OWNERS_ALIASES] and [SIG-CLI Teams]. 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).
|
||||||
|
|
||||||
|
|
||||||
## Contact Information
|
## Contact Information
|
||||||
|
|
||||||
- [Slack channel](https://kubernetes.slack.com/messages/sig-cli)
|
- [Slack channel]
|
||||||
- [Mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-cli)
|
- [Mailing list]
|
||||||
|
|||||||
29
Makefile
29
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.
|
||||||
@@ -29,7 +32,7 @@ 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.1
|
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
|
||||||
@@ -42,7 +45,7 @@ prow-presubmit-check: \
|
|||||||
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.1
|
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
|
||||||
@@ -276,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.1: $(MYGOBIN)/mdrip
|
test-examples-kustomize-against-v4-release: $(MYGOBIN)/mdrip
|
||||||
./hack/testExamplesAgainstKustomize.sh v4@v4.1.2
|
./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
|
||||||
@@ -289,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; \
|
||||||
)
|
)
|
||||||
@@ -304,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 \
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -317,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.6.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 \
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -328,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; \
|
||||||
@@ -339,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 \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
6
OWNERS
6
OWNERS
@@ -1,4 +1,6 @@
|
|||||||
# See https://github.com/kubernetes/community/blob/master/community-membership.md
|
# See https://github.com/kubernetes/community/blob/master/community-membership.md
|
||||||
approvers:
|
approvers:
|
||||||
- kustomize-admins
|
- kustomize-approvers
|
||||||
- kustomize-maintainers
|
|
||||||
|
reviewers:
|
||||||
|
- kustomize-reviewers
|
||||||
|
|||||||
@@ -1,16 +1,30 @@
|
|||||||
# Keep *-admins and *-maintainers list in sync with corresponding lists in
|
# Keep *-owners and *-approvers lists in sync with *-admins and *-maintainers in
|
||||||
# https://github.com/kubernetes/org/blob/main/config/kubernetes-sigs/sig-cli/teams.yaml
|
# https://github.com/kubernetes/org/blob/main/config/kubernetes-sigs/sig-cli/teams.yaml
|
||||||
aliases:
|
aliases:
|
||||||
kustomize-admins:
|
kustomize-owners:
|
||||||
- knverey
|
- knverey
|
||||||
- monopole
|
- monopole
|
||||||
- pwittrock
|
- pwittrock
|
||||||
kustomize-maintainers:
|
kustomize-approvers:
|
||||||
- justinsb
|
- justinsb
|
||||||
- mortent
|
- knverey
|
||||||
|
- monopole
|
||||||
- natasha41575
|
- natasha41575
|
||||||
- phanimarupaka
|
- pwittrock
|
||||||
- Shell32-Natsu
|
kustomize-reviewers:
|
||||||
emeritus-maintainers:
|
- knverey
|
||||||
- liujingfang1
|
- monopole
|
||||||
|
- natasha41575
|
||||||
|
|
||||||
|
kyaml-approvers:
|
||||||
- mengqiy
|
- mengqiy
|
||||||
|
- mortent
|
||||||
|
- phanimarupaka
|
||||||
|
kyaml-reviewers:
|
||||||
|
- mengqiy
|
||||||
|
- mortent
|
||||||
|
- phanimarupaka
|
||||||
|
|
||||||
|
emeritus-approvers:
|
||||||
|
- liujingfang1
|
||||||
|
- Shell32-Natsu
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ will be reflected in the Kubernetes release notes.
|
|||||||
| < v1.14 | n/a |
|
| < v1.14 | n/a |
|
||||||
| v1.14-v1.20 | v2.0.3 |
|
| v1.14-v1.20 | v2.0.3 |
|
||||||
| v1.21 | v4.0.5 |
|
| 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
|
||||||
@@ -151,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
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ func (f Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
// sanity check.
|
// sanity check.
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
f.NameFieldToUpdate.Gvk = f.Referrer.GetGvk()
|
||||||
if err := node.PipeE(fieldspec.Filter{
|
if err := node.PipeE(fieldspec.Filter{
|
||||||
FieldSpec: f.NameFieldToUpdate,
|
FieldSpec: f.NameFieldToUpdate,
|
||||||
SetValue: f.set,
|
SetValue: f.set,
|
||||||
|
|||||||
@@ -250,6 +250,7 @@ metadata:
|
|||||||
name: dep
|
name: dep
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
data:
|
data:
|
||||||
slice:
|
slice:
|
||||||
- false
|
- false
|
||||||
@@ -276,6 +277,7 @@ metadata:
|
|||||||
name: dep
|
name: dep
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
data:
|
data:
|
||||||
1: str
|
1: str
|
||||||
: invalid map key: value='1', tag='` + yaml.NodeTagInt + `'`,
|
: invalid map key: value='1', tag='` + yaml.NodeTagInt + `'`,
|
||||||
|
|||||||
@@ -131,10 +131,11 @@ func getReplacement(nodes []*yaml.RNode, r *types.Replacement) (*yaml.RNode, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !rn.IsNilOrEmpty() {
|
if rn.IsNilOrEmpty() {
|
||||||
return getRefinedValue(r.Source.Options, rn)
|
return nil, fmt.Errorf("fieldPath `%s` is missing for replacement source %s", r.Source.FieldPath, r.Source)
|
||||||
}
|
}
|
||||||
return rn, nil
|
|
||||||
|
return getRefinedValue(r.Source.Options, rn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRefinedValue(options *types.FieldOptions, rn *yaml.RNode) (*yaml.RNode, error) {
|
func getRefinedValue(options *types.FieldOptions, rn *yaml.RNode) (*yaml.RNode, error) {
|
||||||
|
|||||||
@@ -1514,9 +1514,9 @@ kind: Deployment
|
|||||||
metadata:
|
metadata:
|
||||||
name: pre-deploy
|
name: pre-deploy
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/previousNames: deploy,deploy
|
internal.config.kubernetes.io/previousNames: deploy,deploy
|
||||||
config.kubernetes.io/previousKinds: CronJob,Deployment
|
internal.config.kubernetes.io/previousKinds: CronJob,Deployment
|
||||||
config.kubernetes.io/previousNamespaces: default,default
|
internal.config.kubernetes.io/previousNamespaces: default,default
|
||||||
spec:
|
spec:
|
||||||
template:
|
template:
|
||||||
spec:
|
spec:
|
||||||
@@ -1543,9 +1543,9 @@ kind: Deployment
|
|||||||
metadata:
|
metadata:
|
||||||
name: pre-deploy
|
name: pre-deploy
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/previousNames: deploy,deploy
|
internal.config.kubernetes.io/previousNames: deploy,deploy
|
||||||
config.kubernetes.io/previousKinds: CronJob,Deployment
|
internal.config.kubernetes.io/previousKinds: CronJob,Deployment
|
||||||
config.kubernetes.io/previousNamespaces: default,default
|
internal.config.kubernetes.io/previousNamespaces: default,default
|
||||||
spec:
|
spec:
|
||||||
template:
|
template:
|
||||||
spec:
|
spec:
|
||||||
@@ -1556,6 +1556,38 @@ spec:
|
|||||||
name: postgresdb
|
name: postgresdb
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"replacement source.fieldPath does not exist": {
|
||||||
|
input: `apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: ports-from
|
||||||
|
data:
|
||||||
|
grpcPort: 8080
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: ports-to
|
||||||
|
data:
|
||||||
|
grpcPort: 8081
|
||||||
|
`,
|
||||||
|
replacements: `replacements:
|
||||||
|
- source:
|
||||||
|
kind: ConfigMap
|
||||||
|
name: ports-from
|
||||||
|
fieldPath: data.httpPort
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
kind: ConfigMap
|
||||||
|
name: ports-to
|
||||||
|
fieldPaths:
|
||||||
|
- data.grpcPort
|
||||||
|
options:
|
||||||
|
create: true
|
||||||
|
`,
|
||||||
|
expectedErr: "fieldPath `data.httpPort` is missing for replacement source ~G_~V_ConfigMap|~X|ports-from:data.httpPort",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for tn, tc := range testCases {
|
for tn, tc := range testCases {
|
||||||
|
|||||||
@@ -11,6 +11,6 @@ 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.11.0
|
sigs.k8s.io/kustomize/kyaml v0.12.0
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -223,8 +223,8 @@ k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
|
|||||||
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.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA=
|
sigs.k8s.io/kustomize/kyaml v0.12.0 h1:k08l8SLwnKa/eXXB5GW2/OnEc/4gJF90VDFebsOwqw4=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM=
|
sigs.k8s.io/kustomize/kyaml v0.12.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E=
|
||||||
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=
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||||
"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/kyaml/resid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type nameReferenceTransformer struct {
|
type nameReferenceTransformer struct {
|
||||||
@@ -109,11 +110,18 @@ func debug(fMap filterMap) {
|
|||||||
// 'spec/scaleTargetRef/name' field. Return a filter that can do that.
|
// 'spec/scaleTargetRef/name' field. Return a filter that can do that.
|
||||||
func (t *nameReferenceTransformer) determineFilters(
|
func (t *nameReferenceTransformer) determineFilters(
|
||||||
resources []*resource.Resource) (fMap filterMap) {
|
resources []*resource.Resource) (fMap filterMap) {
|
||||||
|
|
||||||
|
// We cache the resource OrgId values because they don't change and otherwise are very visible in a memory pprof
|
||||||
|
resourceOrgIds := make([]resid.ResId, len(resources))
|
||||||
|
for i, resource := range resources {
|
||||||
|
resourceOrgIds[i] = resource.OrgId()
|
||||||
|
}
|
||||||
|
|
||||||
fMap = make(filterMap)
|
fMap = make(filterMap)
|
||||||
for _, backReference := range t.backRefs {
|
for _, backReference := range t.backRefs {
|
||||||
for _, referrerSpec := range backReference.Referrers {
|
for _, referrerSpec := range backReference.Referrers {
|
||||||
for _, res := range resources {
|
for i, res := range resources {
|
||||||
if res.OrgId().IsSelected(&referrerSpec.Gvk) {
|
if resourceOrgIds[i].IsSelected(&referrerSpec.Gvk) {
|
||||||
// If this is true, the res might be a referrer, and if
|
// If this is true, the res might be a referrer, and if
|
||||||
// so, the name reference it holds might need an update.
|
// so, the name reference it holds might need an update.
|
||||||
if resHasField(res, referrerSpec.Path) {
|
if resHasField(res, referrerSpec.Path) {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,3 +168,23 @@ func (ra *ResAccumulator) FixBackReferences() (err error) {
|
|||||||
return ra.Transform(
|
return ra.Transform(
|
||||||
newNameReferenceTransformer(ra.tConfig.NameReference))
|
newNameReferenceTransformer(ra.tConfig.NameReference))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Intersection drops the resources which "other" does not have.
|
||||||
|
func (ra *ResAccumulator) Intersection(other resmap.ResMap) error {
|
||||||
|
for _, curId := range ra.resMap.AllIds() {
|
||||||
|
toDelete := true
|
||||||
|
for _, otherId := range other.AllIds() {
|
||||||
|
if otherId == curId {
|
||||||
|
toDelete = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if toDelete {
|
||||||
|
err := ra.resMap.Remove(curId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -362,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()
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ 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):]
|
||||||
if n[0] == '/' {
|
if len(n) > 0 && n[0] == '/' {
|
||||||
n = n[1:]
|
n = n[1:]
|
||||||
}
|
}
|
||||||
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
|
path, gitRef, gitTimeout, gitSubmodules = peelQuery(n)
|
||||||
|
|||||||
@@ -182,6 +182,12 @@ func TestNewRepoSpecFromUrl_CloneSpecs(t *testing.T) {
|
|||||||
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 tn, tc := range testcases {
|
for tn, tc := range testcases {
|
||||||
t.Run(tn, func(t *testing.T) {
|
t.Run(tn, func(t *testing.T) {
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ func NewFnPlugin(o *types.FnPluginLoadingOptions) *FnPlugin {
|
|||||||
StorageMounts: toStorageMounts(o.Mounts),
|
StorageMounts: toStorageMounts(o.Mounts),
|
||||||
Env: o.Env,
|
Env: o.Env,
|
||||||
AsCurrentUser: o.AsCurrentUser,
|
AsCurrentUser: o.AsCurrentUser,
|
||||||
|
WorkingDir: o.WorkingDir,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -231,10 +231,10 @@ func UpdateResourceOptions(rm resmap.ResMap) (resmap.ResMap, error) {
|
|||||||
if err := r.SetAnnotations(annotations); err != nil {
|
if err := r.SetAnnotations(annotations); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.SetOptions(types.NewGenArgs(
|
if needsHash {
|
||||||
&types.GeneratorArgs{
|
r.EnableHashSuffix()
|
||||||
Behavior: behavior,
|
}
|
||||||
Options: &types.GeneratorOptions{DisableNameSuffixHash: !needsHash}}))
|
r.SetBehavior(types.NewGenerationBehavior(behavior))
|
||||||
}
|
}
|
||||||
return rm, nil
|
return rm, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,17 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/builtins"
|
"sigs.k8s.io/kustomize/api/builtins"
|
||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"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/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 +41,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 +113,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 +156,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")
|
||||||
}
|
}
|
||||||
@@ -205,9 +219,26 @@ func (kt *KustTarget) accumulateTarget(ra *accumulator.ResAccumulator) (
|
|||||||
return nil, errors.Wrapf(
|
return nil, errors.Wrapf(
|
||||||
err, "merging vars %v", kt.kustomization.Vars)
|
err, "merging vars %v", kt.kustomization.Vars)
|
||||||
}
|
}
|
||||||
|
err = kt.IgnoreLocal(ra)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return ra, nil
|
return ra, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IgnoreLocal drops the local resource by checking the annotation "config.kubernetes.io/local-config".
|
||||||
|
func (kt *KustTarget) IgnoreLocal(ra *accumulator.ResAccumulator) error {
|
||||||
|
rf := kt.rFactory.RF()
|
||||||
|
if rf.IncludeLocalConfigs {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
remainRes, err := rf.DropLocalNodes(ra.ResMap().ToRNodeSlice())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ra.Intersection(kt.rFactory.FromResourceSlice(remainRes))
|
||||||
|
}
|
||||||
|
|
||||||
func (kt *KustTarget) runGenerators(
|
func (kt *KustTarget) runGenerators(
|
||||||
ra *accumulator.ResAccumulator) error {
|
ra *accumulator.ResAccumulator) error {
|
||||||
var generators []resmap.Generator
|
var generators []resmap.Generator
|
||||||
@@ -247,7 +278,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 +314,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
|
||||||
}
|
}
|
||||||
@@ -332,16 +362,16 @@ func (kt *KustTarget) removeValidatedByLabel(rm resmap.ResMap) error {
|
|||||||
// 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())
|
||||||
@@ -354,7 +384,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)
|
||||||
@@ -362,7 +392,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)
|
||||||
}
|
}
|
||||||
@@ -371,7 +402,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()
|
||||||
@@ -379,6 +410,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 {
|
||||||
@@ -402,12 +434,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(
|
||||||
@@ -422,11 +454,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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"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"
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
@@ -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"
|
||||||
|
)
|
||||||
@@ -4,25 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/konfig"
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/resid"
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
BuildAnnotationPreviousKinds = konfig.ConfigAnnoDomain + "/previousKinds"
|
|
||||||
BuildAnnotationPreviousNames = konfig.ConfigAnnoDomain + "/previousNames"
|
|
||||||
BuildAnnotationPrefixes = konfig.ConfigAnnoDomain + "/prefixes"
|
|
||||||
BuildAnnotationSuffixes = konfig.ConfigAnnoDomain + "/suffixes"
|
|
||||||
BuildAnnotationPreviousNamespaces = konfig.ConfigAnnoDomain + "/previousNamespaces"
|
|
||||||
|
|
||||||
// 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"
|
|
||||||
Allowed = "allowed"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MakeResIds returns all of an RNode's current and previous Ids
|
// MakeResIds returns all of an RNode's current and previous Ids
|
||||||
func MakeResIds(n *yaml.RNode) ([]resid.ResId, error) {
|
func MakeResIds(n *yaml.RNode) ([]resid.ResId, error) {
|
||||||
var result []resid.ResId
|
var result []resid.ResId
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
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) {
|
||||||
@@ -146,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
|
||||||
@@ -162,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
|
||||||
@@ -184,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"
|
||||||
@@ -209,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
|
||||||
@@ -383,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
|
||||||
@@ -450,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
|
||||||
@@ -459,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
|
||||||
@@ -508,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
|
|
||||||
@@ -685,3 +685,167 @@ spec:
|
|||||||
name: new-name
|
name: new-name
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNameReferenceAfterJsonPatch(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteF("resources.yaml", `
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
bar: bar
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cm
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
foo: foo
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
foo: foo
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: foo
|
||||||
|
image: example
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /path
|
||||||
|
name: myvol
|
||||||
|
volumes:
|
||||||
|
- configMap:
|
||||||
|
name: cm
|
||||||
|
name: myvol
|
||||||
|
`)
|
||||||
|
th.WriteK(".", `
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
namePrefix: foo-
|
||||||
|
resources:
|
||||||
|
- resources.yaml
|
||||||
|
patches:
|
||||||
|
- target:
|
||||||
|
group: apps
|
||||||
|
version: v1
|
||||||
|
name: foo
|
||||||
|
patch: |
|
||||||
|
- op: replace
|
||||||
|
path: /kind
|
||||||
|
value: Deployment
|
||||||
|
`)
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `apiVersion: v1
|
||||||
|
data:
|
||||||
|
bar: bar
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: foo-cm
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: foo-foo
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
foo: foo
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
foo: foo
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: example
|
||||||
|
name: foo
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /path
|
||||||
|
name: myvol
|
||||||
|
volumes:
|
||||||
|
- configMap:
|
||||||
|
name: foo-cm
|
||||||
|
name: myvol
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNameReferenceAfterJsonPatchConfigMapGenerator(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteF("statefulset.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
foo: foo
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
foo: foo
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: foo
|
||||||
|
image: example
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /path
|
||||||
|
name: myvol
|
||||||
|
volumes:
|
||||||
|
- configMap:
|
||||||
|
name: cm
|
||||||
|
name: myvol
|
||||||
|
`)
|
||||||
|
th.WriteK(".", `
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- statefulset.yaml
|
||||||
|
patches:
|
||||||
|
- target:
|
||||||
|
group: apps
|
||||||
|
version: v1
|
||||||
|
name: foo
|
||||||
|
patch: |
|
||||||
|
- op: replace
|
||||||
|
path: /kind
|
||||||
|
value: Deployment
|
||||||
|
configMapGenerator:
|
||||||
|
- name: cm
|
||||||
|
literals:
|
||||||
|
- bar=bar
|
||||||
|
`)
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
foo: foo
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
foo: foo
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: example
|
||||||
|
name: foo
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /path
|
||||||
|
name: myvol
|
||||||
|
volumes:
|
||||||
|
- configMap:
|
||||||
|
name: cm-8hm8224gfd
|
||||||
|
name: myvol
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
bar: bar
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cm-8hm8224gfd
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import (
|
|||||||
// used instead of performing an exec to a kustomize CLI subprocess.
|
// used instead of performing an exec to a kustomize CLI subprocess.
|
||||||
// To use, load a filesystem with kustomization files (any
|
// To use, load a filesystem with kustomization files (any
|
||||||
// number of overlays and bases), then make a Kustomizer
|
// number of overlays and bases), then make a Kustomizer
|
||||||
// injected with the given fileystem, then call Run.
|
// injected with the given filesystem, then call Run.
|
||||||
type Kustomizer struct {
|
type Kustomizer struct {
|
||||||
options *Options
|
options *Options
|
||||||
depProvider *provider.DepProvider
|
depProvider *provider.DepProvider
|
||||||
|
|||||||
70
api/krusty/localconfig_test.go
Normal file
70
api/krusty/localconfig_test.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package krusty_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This test checks that if a resource is annotated as "local-config", this resource won't be ignored until
|
||||||
|
// all transformations have completed. This makes sure the local resource can be used as a transformation input.
|
||||||
|
// See https://github.com/kubernetes-sigs/kustomize/issues/4124 for details.
|
||||||
|
func TestSKipLocalConfigAfterTransform(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteK(".", `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- pod.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
transformers:
|
||||||
|
- replacement.yaml
|
||||||
|
`)
|
||||||
|
th.WriteF("pod.yaml", `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: buildup
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/local-config: "true"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: nginx
|
||||||
|
`)
|
||||||
|
th.WriteF("deployment.yaml", `apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: buildup
|
||||||
|
`)
|
||||||
|
th.WriteF("replacement.yaml", `
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: ReplacementTransformer
|
||||||
|
metadata:
|
||||||
|
name: buildup
|
||||||
|
replacements:
|
||||||
|
- source:
|
||||||
|
kind: Pod
|
||||||
|
fieldPath: spec
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
kind: Deployment
|
||||||
|
fieldPaths:
|
||||||
|
- spec.template.spec
|
||||||
|
options:
|
||||||
|
create: true
|
||||||
|
`)
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: buildup
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
|
name: app
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -37,6 +42,26 @@ spec:
|
|||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeOtherCustomResource(th kusttest_test.Harness, filepath string) {
|
||||||
|
th.WriteF(filepath, `
|
||||||
|
apiVersion: v1alpha1
|
||||||
|
kind: MyCRD
|
||||||
|
metadata:
|
||||||
|
name: service
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: server
|
||||||
|
command: example
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
protocol: TCP
|
||||||
|
containerPort: 8080
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func writeTestComponentWithCustomSchema(th kusttest_test.Harness) {
|
func writeTestComponentWithCustomSchema(th kusttest_test.Harness) {
|
||||||
writeTestSchema(th, "comp/")
|
writeTestSchema(th, "comp/")
|
||||||
openapi.ResetOpenAPI()
|
openapi.ResetOpenAPI()
|
||||||
@@ -69,6 +94,32 @@ patchesStrategicMerge:
|
|||||||
image: nginx
|
image: nginx
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const customSchemaPatchMultipleGvks = `
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- |-
|
||||||
|
apiVersion: example.com/v1alpha1
|
||||||
|
kind: MyCRD
|
||||||
|
metadata:
|
||||||
|
name: service
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: nginx
|
||||||
|
- |-
|
||||||
|
apiVersion: v1alpha1
|
||||||
|
kind: MyCRD
|
||||||
|
metadata:
|
||||||
|
name: service
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: nginx
|
||||||
|
`
|
||||||
|
|
||||||
const patchedCustomResource = `
|
const patchedCustomResource = `
|
||||||
apiVersion: example.com/v1alpha1
|
apiVersion: example.com/v1alpha1
|
||||||
kind: MyCRD
|
kind: MyCRD
|
||||||
@@ -103,6 +154,69 @@ openapi:
|
|||||||
th.AssertActualEqualsExpected(m, patchedCustomResource)
|
th.AssertActualEqualsExpected(m, patchedCustomResource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCustomOpenApiFieldWithTwoGvks(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteK(".", `
|
||||||
|
resources:
|
||||||
|
- mycrd.yaml
|
||||||
|
- myothercrd.yaml
|
||||||
|
openapi:
|
||||||
|
path: mycrd_schema.json
|
||||||
|
`+customSchemaPatchMultipleGvks)
|
||||||
|
writeCustomResource(th, "mycrd.yaml")
|
||||||
|
writeOtherCustomResource(th, "myothercrd.yaml")
|
||||||
|
writeTestSchema(th, "./")
|
||||||
|
openapi.ResetOpenAPI()
|
||||||
|
m := th.Run(".", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `apiVersion: example.com/v1alpha1
|
||||||
|
kind: MyCRD
|
||||||
|
metadata:
|
||||||
|
name: service
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- command: example
|
||||||
|
image: nginx
|
||||||
|
name: server
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: grpc
|
||||||
|
protocol: TCP
|
||||||
|
---
|
||||||
|
apiVersion: v1alpha1
|
||||||
|
kind: MyCRD
|
||||||
|
metadata:
|
||||||
|
name: service
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- command: example
|
||||||
|
image: nginx
|
||||||
|
name: server
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: grpc
|
||||||
|
protocol: TCP
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 +225,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 +311,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 +329,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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package krusty_test
|
package krusty_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -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()))
|
||||||
|
}
|
||||||
|
|||||||
@@ -342,3 +342,143 @@ spec:
|
|||||||
name: nginx
|
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
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
5
api/krusty/testdata/customschema.json
vendored
5
api/krusty/testdata/customschema.json
vendored
@@ -34,6 +34,11 @@
|
|||||||
"group": "example.com",
|
"group": "example.com",
|
||||||
"kind": "MyCRD",
|
"kind": "MyCRD",
|
||||||
"version": "v1alpha1"
|
"version": "v1alpha1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "",
|
||||||
|
"kind": "MyCRD",
|
||||||
|
"version": "v1alpha1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
78
api/krusty/testdata/customschema.yaml
vendored
Normal file
78
api/krusty/testdata/customschema.yaml
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
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
|
||||||
|
- group: ""
|
||||||
|
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
|
||||||
@@ -219,8 +219,10 @@ BAR=baz
|
|||||||
}
|
}
|
||||||
r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, tc.input)
|
r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, tc.input)
|
||||||
assert.NoError(t, err, tc.description)
|
assert.NoError(t, err, tc.description)
|
||||||
|
r.RemoveBuildAnnotations()
|
||||||
rYaml, err := r.AsYaml()
|
rYaml, err := r.AsYaml()
|
||||||
assert.NoError(t, err, tc.description)
|
assert.NoError(t, err, tc.description)
|
||||||
|
tc.expected.RemoveBuildAnnotations()
|
||||||
expYaml, err := tc.expected.AsYaml()
|
expYaml, err := tc.expected.AsYaml()
|
||||||
assert.NoError(t, err, tc.description)
|
assert.NoError(t, err, tc.description)
|
||||||
assert.Equal(t, expYaml, rYaml)
|
assert.Equal(t, expYaml, rYaml)
|
||||||
@@ -252,6 +254,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
actual.RemoveBuildAnnotations()
|
||||||
actYaml, err := actual.AsYaml()
|
actYaml, err := actual.AsYaml()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,10 @@ type ResMap interface {
|
|||||||
// self, then its behavior _cannot_ be merge or replace.
|
// self, then its behavior _cannot_ be merge or replace.
|
||||||
AbsorbAll(ResMap) error
|
AbsorbAll(ResMap) error
|
||||||
|
|
||||||
|
// AnnotateAll annotates all resources in the ResMap with
|
||||||
|
// the provided key value pair.
|
||||||
|
AnnotateAll(key string, value string) error
|
||||||
|
|
||||||
// AsYaml returns the yaml form of resources.
|
// AsYaml returns the yaml form of resources.
|
||||||
AsYaml() ([]byte, error)
|
AsYaml() ([]byte, error)
|
||||||
|
|
||||||
@@ -210,6 +214,35 @@ type ResMap interface {
|
|||||||
// namespaces. Cluster wide objects are never excluded.
|
// namespaces. Cluster wide objects are never excluded.
|
||||||
SubsetThatCouldBeReferencedByResource(*resource.Resource) ResMap
|
SubsetThatCouldBeReferencedByResource(*resource.Resource) ResMap
|
||||||
|
|
||||||
|
// DeAnchor replaces YAML aliases with structured data copied from anchors.
|
||||||
|
// This cannot be undone; if desired, call DeepCopy first.
|
||||||
|
// Subsequent marshalling to YAML will no longer have anchor
|
||||||
|
// definitions ('&') or aliases ('*').
|
||||||
|
//
|
||||||
|
// Anchors are not expected to work across YAML 'documents'.
|
||||||
|
// If three resources are loaded from one file containing three YAML docs:
|
||||||
|
//
|
||||||
|
// {resourceA}
|
||||||
|
// ---
|
||||||
|
// {resourceB}
|
||||||
|
// ---
|
||||||
|
// {resourceC}
|
||||||
|
//
|
||||||
|
// then anchors defined in A cannot be seen from B and C and vice versa.
|
||||||
|
// OTOH, cross-resource links (a field in B referencing fields in A) will
|
||||||
|
// work if the resources are gathered in a ResourceList:
|
||||||
|
//
|
||||||
|
// apiVersion: config.kubernetes.io/v1
|
||||||
|
// kind: ResourceList
|
||||||
|
// metadata:
|
||||||
|
// name: someList
|
||||||
|
// items:
|
||||||
|
// - {resourceA}
|
||||||
|
// - {resourceB}
|
||||||
|
// - {resourceC}
|
||||||
|
//
|
||||||
|
DeAnchor() error
|
||||||
|
|
||||||
// DeepCopy copies the ResMap and underlying resources.
|
// DeepCopy copies the ResMap and underlying resources.
|
||||||
DeepCopy() ResMap
|
DeepCopy() ResMap
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"sigs.k8s.io/kustomize/api/filters/annotations"
|
||||||
"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"
|
||||||
@@ -531,6 +532,19 @@ func (m *resWrangler) appendReplaceOrMerge(res *resource.Resource) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AnnotateAll implements ResMap
|
||||||
|
func (m *resWrangler) AnnotateAll(key string, value string) error {
|
||||||
|
return m.ApplyFilter(annotations.Filter{
|
||||||
|
Annotations: map[string]string{
|
||||||
|
key: value,
|
||||||
|
},
|
||||||
|
FsSlice: []types.FieldSpec{{
|
||||||
|
Path: "metadata/annotations",
|
||||||
|
CreateIfNotPresent: true,
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Select returns a list of resources that
|
// Select returns a list of resources that
|
||||||
// are selected by a Selector
|
// are selected by a Selector
|
||||||
func (m *resWrangler) Select(s types.Selector) ([]*resource.Resource, error) {
|
func (m *resWrangler) Select(s types.Selector) ([]*resource.Resource, error) {
|
||||||
@@ -593,6 +607,16 @@ func (m *resWrangler) ToRNodeSlice() []*kyaml.RNode {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeAnchor implements ResMap.
|
||||||
|
func (m *resWrangler) DeAnchor() (err error) {
|
||||||
|
for i := range m.rList {
|
||||||
|
if err = m.rList[i].DeAnchor(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ApplySmPatch applies the patch, and errors on Id collisions.
|
// ApplySmPatch applies the patch, and errors on Id collisions.
|
||||||
func (m *resWrangler) ApplySmPatch(
|
func (m *resWrangler) ApplySmPatch(
|
||||||
selectedSet *resource.IdSet, patch *resource.Resource) error {
|
selectedSet *resource.IdSet, patch *resource.Resource) error {
|
||||||
|
|||||||
@@ -343,9 +343,9 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
|
|||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"name": "new-alice",
|
"name": "new-alice",
|
||||||
"annotations": map[string]interface{}{
|
"annotations": map[string]interface{}{
|
||||||
"config.kubernetes.io/previousKinds": "ConfigMap",
|
"internal.config.kubernetes.io/previousKinds": "ConfigMap",
|
||||||
"config.kubernetes.io/previousNames": "alice",
|
"internal.config.kubernetes.io/previousNames": "alice",
|
||||||
"config.kubernetes.io/previousNamespaces": "default",
|
"internal.config.kubernetes.io/previousNamespaces": "default",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -356,9 +356,9 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
|
|||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"name": "new-bob",
|
"name": "new-bob",
|
||||||
"annotations": map[string]interface{}{
|
"annotations": map[string]interface{}{
|
||||||
"config.kubernetes.io/previousKinds": "ConfigMap,ConfigMap",
|
"internal.config.kubernetes.io/previousKinds": "ConfigMap,ConfigMap",
|
||||||
"config.kubernetes.io/previousNames": "bob,bob2",
|
"internal.config.kubernetes.io/previousNames": "bob,bob2",
|
||||||
"config.kubernetes.io/previousNamespaces": "default,default",
|
"internal.config.kubernetes.io/previousNamespaces": "default,default",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -370,9 +370,9 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
|
|||||||
"name": "new-bob",
|
"name": "new-bob",
|
||||||
"namespace": "new-happy",
|
"namespace": "new-happy",
|
||||||
"annotations": map[string]interface{}{
|
"annotations": map[string]interface{}{
|
||||||
"config.kubernetes.io/previousKinds": "ConfigMap",
|
"internal.config.kubernetes.io/previousKinds": "ConfigMap",
|
||||||
"config.kubernetes.io/previousNames": "bob",
|
"internal.config.kubernetes.io/previousNames": "bob",
|
||||||
"config.kubernetes.io/previousNamespaces": "happy",
|
"internal.config.kubernetes.io/previousNamespaces": "happy",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -384,9 +384,9 @@ func TestGetMatchingResourcesByAnyId(t *testing.T) {
|
|||||||
"name": "charlie",
|
"name": "charlie",
|
||||||
"namespace": "happy",
|
"namespace": "happy",
|
||||||
"annotations": map[string]interface{}{
|
"annotations": map[string]interface{}{
|
||||||
"config.kubernetes.io/previousKinds": "ConfigMap",
|
"internal.config.kubernetes.io/previousKinds": "ConfigMap",
|
||||||
"config.kubernetes.io/previousNames": "charlie",
|
"internal.config.kubernetes.io/previousNames": "charlie",
|
||||||
"config.kubernetes.io/previousNamespaces": "default",
|
"internal.config.kubernetes.io/previousNamespaces": "default",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -845,6 +845,8 @@ func TestAbsorbAll(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
w := makeMap1()
|
w := makeMap1()
|
||||||
assert.NoError(t, w.AbsorbAll(makeMap2(types.BehaviorMerge)))
|
assert.NoError(t, w.AbsorbAll(makeMap2(types.BehaviorMerge)))
|
||||||
|
expected.RemoveBuildAnnotations()
|
||||||
|
w.RemoveBuildAnnotations()
|
||||||
assert.NoError(t, expected.ErrorIfNotEqualLists(w))
|
assert.NoError(t, expected.ErrorIfNotEqualLists(w))
|
||||||
w = makeMap1()
|
w = makeMap1()
|
||||||
assert.NoError(t, w.AbsorbAll(nil))
|
assert.NoError(t, w.AbsorbAll(nil))
|
||||||
@@ -853,6 +855,7 @@ func TestAbsorbAll(t *testing.T) {
|
|||||||
w = makeMap1()
|
w = makeMap1()
|
||||||
w2 := makeMap2(types.BehaviorReplace)
|
w2 := makeMap2(types.BehaviorReplace)
|
||||||
assert.NoError(t, w.AbsorbAll(w2))
|
assert.NoError(t, w.AbsorbAll(w2))
|
||||||
|
w2.RemoveBuildAnnotations()
|
||||||
assert.NoError(t, w2.ErrorIfNotEqualLists(w))
|
assert.NoError(t, w2.ErrorIfNotEqualLists(w))
|
||||||
w = makeMap1()
|
w = makeMap1()
|
||||||
w2 = makeMap2(types.BehaviorUnspecified)
|
w2 = makeMap2(types.BehaviorUnspecified)
|
||||||
@@ -899,6 +902,100 @@ rules:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeAnchorSingleDoc(t *testing.T) {
|
||||||
|
input := `apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: wildcard
|
||||||
|
data:
|
||||||
|
color: &color-used blue
|
||||||
|
feeling: *color-used
|
||||||
|
`
|
||||||
|
rm, err := rmF.NewResMapFromBytes([]byte(input))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, rm.DeAnchor())
|
||||||
|
yaml, err := rm.AsYaml()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, strings.TrimSpace(`
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
color: blue
|
||||||
|
feeling: blue
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: wildcard
|
||||||
|
`), strings.TrimSpace(string(yaml)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anchor references don't cross YAML document boundaries.
|
||||||
|
func TestDeAnchorMultiDoc(t *testing.T) {
|
||||||
|
input := `apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: betty
|
||||||
|
data:
|
||||||
|
color: &color-used blue
|
||||||
|
feeling: *color-used
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: bob
|
||||||
|
data:
|
||||||
|
color: red
|
||||||
|
feeling: *color-used
|
||||||
|
`
|
||||||
|
_, err := rmF.NewResMapFromBytes([]byte(input))
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "unknown anchor 'color-used' referenced")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anchor references cross list elements in a ResourceList.
|
||||||
|
func TestDeAnchorResourceList(t *testing.T) {
|
||||||
|
input := `apiVersion: config.kubernetes.io/v1
|
||||||
|
kind: ResourceList
|
||||||
|
metadata:
|
||||||
|
name: aShortList
|
||||||
|
items:
|
||||||
|
- apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: betty
|
||||||
|
data:
|
||||||
|
color: &color-used blue
|
||||||
|
feeling: *color-used
|
||||||
|
- apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: bob
|
||||||
|
data:
|
||||||
|
color: red
|
||||||
|
feeling: *color-used
|
||||||
|
`
|
||||||
|
rm, err := rmF.NewResMapFromBytes([]byte(input))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, rm.DeAnchor())
|
||||||
|
yaml, err := rm.AsYaml()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, strings.TrimSpace(`
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
color: blue
|
||||||
|
feeling: blue
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: betty
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
color: red
|
||||||
|
feeling: blue
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: bob
|
||||||
|
`), strings.TrimSpace(string(yaml)))
|
||||||
|
}
|
||||||
|
|
||||||
func TestApplySmPatch_General(t *testing.T) {
|
func TestApplySmPatch_General(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
myDeployment = "Deployment"
|
myDeployment = "Deployment"
|
||||||
|
|||||||
@@ -64,18 +64,23 @@ func (rf *Factory) FromMapAndOption(
|
|||||||
// TODO: return err instead of log.
|
// TODO: return err instead of log.
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
return rf.makeOne(n, types.NewGenArgs(args))
|
return rf.makeOne(n, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeOne returns a new instance of Resource.
|
// makeOne returns a new instance of Resource.
|
||||||
func (rf *Factory) makeOne(rn *yaml.RNode, o *types.GenArgs) *Resource {
|
func (rf *Factory) makeOne(rn *yaml.RNode, o *types.GeneratorArgs) *Resource {
|
||||||
if rn == nil {
|
if rn == nil {
|
||||||
log.Fatal("RNode must not be null")
|
log.Fatal("RNode must not be null")
|
||||||
}
|
}
|
||||||
if o == nil {
|
resource := &Resource{RNode: *rn}
|
||||||
o = types.NewGenArgs(nil)
|
if o != nil {
|
||||||
|
if o.Options == nil || !o.Options.DisableNameSuffixHash {
|
||||||
|
resource.EnableHashSuffix()
|
||||||
|
}
|
||||||
|
resource.SetBehavior(types.NewGenerationBehavior(o.Behavior))
|
||||||
}
|
}
|
||||||
return &Resource{RNode: *rn, options: o}
|
|
||||||
|
return resource
|
||||||
}
|
}
|
||||||
|
|
||||||
// SliceFromPatches returns a slice of resources given a patch path
|
// SliceFromPatches returns a slice of resources given a patch path
|
||||||
@@ -119,14 +124,34 @@ func (rf *Factory) SliceFromBytes(in []byte) ([]*Resource, error) {
|
|||||||
return rf.resourcesFromRNodes(nodes), nil
|
return rf.resourcesFromRNodes(nodes), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DropLocalNodes removes the local nodes by default. Local nodes are detected via the annotation `config.kubernetes.io/local-config: "true"`
|
||||||
|
func (rf *Factory) DropLocalNodes(nodes []*yaml.RNode) ([]*Resource, error) {
|
||||||
|
var result []*yaml.RNode
|
||||||
|
for _, node := range nodes {
|
||||||
|
if node.IsNilOrEmpty() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
md, err := node.GetValidatedMetadata()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf.IncludeLocalConfigs {
|
||||||
|
result = append(result, node)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
localConfig, exist := md.ObjectMeta.Annotations[konfig.IgnoredByKustomizeAnnotation]
|
||||||
|
if !exist || localConfig == "false" {
|
||||||
|
result = append(result, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rf.resourcesFromRNodes(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
// ResourcesFromRNodes converts RNodes to Resources.
|
// ResourcesFromRNodes converts RNodes to Resources.
|
||||||
func (rf *Factory) ResourcesFromRNodes(
|
func (rf *Factory) ResourcesFromRNodes(
|
||||||
nodes []*yaml.RNode) (result []*Resource, err error) {
|
nodes []*yaml.RNode) (result []*Resource, err error) {
|
||||||
nodes, err = rf.dropBadNodes(nodes)
|
return rf.DropLocalNodes(nodes)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return rf.resourcesFromRNodes(nodes), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// resourcesFromRNode assumes all nodes are good.
|
// resourcesFromRNode assumes all nodes are good.
|
||||||
@@ -138,7 +163,7 @@ func (rf *Factory) resourcesFromRNodes(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rf *Factory) RNodesFromBytes(b []byte) (result []*yaml.RNode, err error) {
|
func (rf *Factory) RNodesFromBytes(b []byte) ([]*yaml.RNode, error) {
|
||||||
nodes, err := kio.FromBytes(b)
|
nodes, err := kio.FromBytes(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -147,9 +172,17 @@ func (rf *Factory) RNodesFromBytes(b []byte) (result []*yaml.RNode, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return rf.inlineAnyEmbeddedLists(nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// inlineAnyEmbeddedLists scans the RNode slice for nodes named FooList.
|
||||||
|
// Such nodes are expected to be lists of resources, each of type Foo.
|
||||||
|
// These lists are replaced in the result by their inlined resources.
|
||||||
|
func (rf *Factory) inlineAnyEmbeddedLists(
|
||||||
|
nodes []*yaml.RNode) (result []*yaml.RNode, err error) {
|
||||||
|
var n0 *yaml.RNode
|
||||||
for len(nodes) > 0 {
|
for len(nodes) > 0 {
|
||||||
n0 := nodes[0]
|
n0, nodes = nodes[0], nodes[1:]
|
||||||
nodes = nodes[1:]
|
|
||||||
kind := n0.GetKind()
|
kind := n0.GetKind()
|
||||||
if !strings.HasSuffix(kind, "List") {
|
if !strings.HasSuffix(kind, "List") {
|
||||||
result = append(result, n0)
|
result = append(result, n0)
|
||||||
@@ -159,7 +192,7 @@ func (rf *Factory) RNodesFromBytes(b []byte) (result []*yaml.RNode, err error) {
|
|||||||
var m map[string]interface{}
|
var m map[string]interface{}
|
||||||
m, err = n0.Map()
|
m, err = n0.Map()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("trouble expanding list of %s; %w", kind, err)
|
||||||
}
|
}
|
||||||
items, ok := m["items"]
|
items, ok := m["items"]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -211,38 +244,20 @@ func (rf *Factory) convertObjectSliceToNodeSlice(
|
|||||||
func (rf *Factory) dropBadNodes(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
func (rf *Factory) dropBadNodes(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
var result []*yaml.RNode
|
var result []*yaml.RNode
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
ignore, err := rf.shouldIgnore(n)
|
if n.IsNilOrEmpty() {
|
||||||
if err != nil {
|
continue
|
||||||
|
}
|
||||||
|
if _, err := n.GetValidatedMetadata(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !ignore {
|
if foundNil, path := n.HasNilEntryInList(); foundNil {
|
||||||
result = append(result, n)
|
return nil, fmt.Errorf("empty item at %v in object %v", path, n)
|
||||||
}
|
}
|
||||||
|
result = append(result, n)
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldIgnore returns true if there's some reason to ignore the node.
|
|
||||||
func (rf *Factory) shouldIgnore(n *yaml.RNode) (bool, error) {
|
|
||||||
if n.IsNilOrEmpty() {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
if !rf.IncludeLocalConfigs {
|
|
||||||
md, err := n.GetValidatedMetadata()
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
_, ignore := md.ObjectMeta.Annotations[konfig.IgnoredByKustomizeAnnotation]
|
|
||||||
if ignore {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if foundNil, path := n.HasNilEntryInList(); foundNil {
|
|
||||||
return true, fmt.Errorf("empty item at %v in object %v", path, n)
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SliceFromBytesWithNames unmarshals bytes into a Resource slice with specified original
|
// SliceFromBytesWithNames unmarshals bytes into a Resource slice with specified original
|
||||||
// name.
|
// name.
|
||||||
func (rf *Factory) SliceFromBytesWithNames(names []string, in []byte) ([]*Resource, error) {
|
func (rf *Factory) SliceFromBytesWithNames(names []string, in []byte) ([]*Resource, error) {
|
||||||
@@ -265,7 +280,7 @@ func (rf *Factory) MakeConfigMap(kvLdr ifc.KvLoader, args *types.ConfigMapArgs)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return rf.makeOne(rn, types.NewGenArgs(&args.GeneratorArgs)), nil
|
return rf.makeOne(rn, &args.GeneratorArgs), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeSecret makes an instance of Resource for Secret
|
// MakeSecret makes an instance of Resource for Secret
|
||||||
@@ -274,5 +289,5 @@ func (rf *Factory) MakeSecret(kvLdr ifc.KvLoader, args *types.SecretArgs) (*Reso
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return rf.makeOne(rn, types.NewGenArgs(&args.GeneratorArgs)), nil
|
return rf.makeOne(rn, &args.GeneratorArgs), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package resource_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -13,9 +13,10 @@ import (
|
|||||||
. "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/filesys"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSliceFromBytes(t *testing.T) {
|
func TestRNodesFromBytes(t *testing.T) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
input string
|
input string
|
||||||
expected []string
|
expected []string
|
||||||
@@ -399,60 +400,11 @@ binaryData:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceFromBytesMore(t *testing.T) {
|
func TestMoreRNodesFromBytes(t *testing.T) {
|
||||||
testConfigMap :=
|
|
||||||
map[string]interface{}{
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "ConfigMap",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "winnie",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
testDeploymentSpec := map[string]interface{}{
|
|
||||||
"template": map[string]interface{}{
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"hostAliases": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"hostnames": []interface{}{
|
|
||||||
"a.example.com",
|
|
||||||
},
|
|
||||||
"ip": "8.8.8.8",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
testDeploymentA := map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deployment-a",
|
|
||||||
},
|
|
||||||
"spec": testDeploymentSpec,
|
|
||||||
}
|
|
||||||
testDeploymentB := map[string]interface{}{
|
|
||||||
"apiVersion": "apps/v1",
|
|
||||||
"kind": "Deployment",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "deployment-b",
|
|
||||||
},
|
|
||||||
"spec": testDeploymentSpec,
|
|
||||||
}
|
|
||||||
testDeploymentList :=
|
|
||||||
map[string]interface{}{
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "DeploymentList",
|
|
||||||
"items": []interface{}{
|
|
||||||
testDeploymentA,
|
|
||||||
testDeploymentB,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type expected struct {
|
type expected struct {
|
||||||
out []map[string]interface{}
|
out []string
|
||||||
isErr bool
|
isErr bool
|
||||||
}
|
}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
input []byte
|
input []byte
|
||||||
exp expected
|
exp expected
|
||||||
@@ -465,16 +417,16 @@ func TestSliceFromBytesMore(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"noBytes": {
|
"noBytes": {
|
||||||
input: []byte{},
|
input: []byte{},
|
||||||
exp: expected{
|
exp: expected{},
|
||||||
out: []map[string]interface{}{},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"goodJson": {
|
"goodJson": {
|
||||||
input: []byte(`
|
input: []byte(`
|
||||||
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
|
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
|
||||||
`),
|
`),
|
||||||
exp: expected{
|
exp: expected{
|
||||||
out: []map[string]interface{}{testConfigMap},
|
out: []string{
|
||||||
|
`{"apiVersion": "v1", "kind": "ConfigMap", "metadata": {"name": "winnie"}}`,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"goodYaml1": {
|
"goodYaml1": {
|
||||||
@@ -485,7 +437,12 @@ metadata:
|
|||||||
name: winnie
|
name: winnie
|
||||||
`),
|
`),
|
||||||
exp: expected{
|
exp: expected{
|
||||||
out: []map[string]interface{}{testConfigMap},
|
out: []string{`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie
|
||||||
|
`},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"goodYaml2": {
|
"goodYaml2": {
|
||||||
@@ -501,26 +458,17 @@ metadata:
|
|||||||
name: winnie
|
name: winnie
|
||||||
`),
|
`),
|
||||||
exp: expected{
|
exp: expected{
|
||||||
out: []map[string]interface{}{testConfigMap, testConfigMap},
|
out: []string{`
|
||||||
},
|
|
||||||
},
|
|
||||||
"localConfigYaml": {
|
|
||||||
input: []byte(`
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: winnie-skip
|
|
||||||
annotations:
|
|
||||||
# this annotation causes the Resource to be ignored by kustomize
|
|
||||||
config.kubernetes.io/local-config: ""
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
name: winnie
|
name: winnie
|
||||||
`),
|
`, `
|
||||||
exp: expected{
|
apiVersion: v1
|
||||||
out: []map[string]interface{}{testConfigMap},
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie
|
||||||
|
`},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"garbageInOneOfTwoObjects": {
|
"garbageInOneOfTwoObjects": {
|
||||||
@@ -545,7 +493,7 @@ WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
|
|||||||
|
|
||||||
`),
|
`),
|
||||||
exp: expected{
|
exp: expected{
|
||||||
out: []map[string]interface{}{},
|
out: []string{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Missing .metadata.name in object": {
|
"Missing .metadata.name in object": {
|
||||||
@@ -591,9 +539,18 @@ items:
|
|||||||
name: winnie
|
name: winnie
|
||||||
`),
|
`),
|
||||||
exp: expected{
|
exp: expected{
|
||||||
out: []map[string]interface{}{
|
out: []string{`
|
||||||
testConfigMap,
|
apiVersion: v1
|
||||||
testConfigMap},
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie
|
||||||
|
`, `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie
|
||||||
|
`,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"ConfigMapList": {
|
"ConfigMapList": {
|
||||||
@@ -611,9 +568,9 @@ items:
|
|||||||
name: winnie
|
name: winnie
|
||||||
`),
|
`),
|
||||||
exp: expected{
|
exp: expected{
|
||||||
out: []map[string]interface{}{
|
out: []string{
|
||||||
testConfigMap,
|
`{"apiVersion": "v1", "kind": "ConfigMap", "metadata": {"name": "winnie"}}`,
|
||||||
testConfigMap,
|
`{"apiVersion": "v1", "kind": "ConfigMap", "metadata": {"name": "winnie"}}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -626,7 +583,7 @@ items:
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: deployment-a
|
name: deployment-a
|
||||||
spec: &hostAliases
|
spec: &foo
|
||||||
template:
|
template:
|
||||||
spec:
|
spec:
|
||||||
hostAliases:
|
hostAliases:
|
||||||
@@ -638,23 +595,39 @@ items:
|
|||||||
metadata:
|
metadata:
|
||||||
name: deployment-b
|
name: deployment-b
|
||||||
spec:
|
spec:
|
||||||
<<: *hostAliases
|
*foo
|
||||||
`),
|
`),
|
||||||
exp: expected{
|
exp: expected{
|
||||||
// TODO(3271): This should work.
|
out: []string{
|
||||||
// https://github.com/kubernetes-sigs/kustomize/issues/3271
|
`{"apiVersion": "apps/v1", "kind": "Deployment", "metadata": {"name": "deployment-a"}, ` +
|
||||||
// json.Marshal(obj) fails on the 2nd list item.
|
`"spec": {"template": {"spec": {"hostAliases": [{"hostnames": ["a.example.com"], "ip": "8.8.8.8"}]}}}}`,
|
||||||
// The value of the 1st list item's first spec field is
|
`{"apiVersion": "apps/v1", "kind": "Deployment", "metadata": {"name": "deployment-b"}, ` +
|
||||||
// map[string]interface{}
|
`"spec": {"template": {"spec": {"hostAliases": [{"hostnames": ["a.example.com"], "ip": "8.8.8.8"}]}}}}`},
|
||||||
// The value of the 2nd list item's first spec field is
|
},
|
||||||
// map[interface{}]interface{}
|
},
|
||||||
// which causes a encoding/json.UnsupportedTypeError.
|
"simpleAnchor": {
|
||||||
isErr: true,
|
input: []byte(`
|
||||||
out: []map[string]interface{}{testDeploymentList},
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: wildcard
|
||||||
|
data:
|
||||||
|
color: &color-used blue
|
||||||
|
feeling: *color-used
|
||||||
|
`),
|
||||||
|
exp: expected{
|
||||||
|
out: []string{`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: wildcard
|
||||||
|
data:
|
||||||
|
color: blue
|
||||||
|
feeling: blue
|
||||||
|
`},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for n := range testCases {
|
for n := range testCases {
|
||||||
tc := testCases[n]
|
tc := testCases[n]
|
||||||
t.Run(n, func(t *testing.T) {
|
t.Run(n, func(t *testing.T) {
|
||||||
@@ -666,15 +639,100 @@ items:
|
|||||||
assert.False(t, tc.exp.isErr)
|
assert.False(t, tc.exp.isErr)
|
||||||
assert.Equal(t, len(tc.exp.out), len(rs))
|
assert.Equal(t, len(tc.exp.out), len(rs))
|
||||||
for i := range rs {
|
for i := range rs {
|
||||||
rsMap, err := rs[i].Map()
|
actual, err := rs[i].String()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(
|
assert.Equal(
|
||||||
t, fmt.Sprintf("%v", tc.exp.out[i]), fmt.Sprintf("%v", rsMap))
|
t, strings.TrimSpace(tc.exp.out[i]), strings.TrimSpace(actual))
|
||||||
m, _ := rs[i].Map()
|
}
|
||||||
if !reflect.DeepEqual(tc.exp.out[i], m) {
|
})
|
||||||
t.Fatalf("%s:\nexpected: %v\n actual: %v",
|
}
|
||||||
n, tc.exp.out[i], m)
|
}
|
||||||
}
|
|
||||||
|
func TestDropLocalNodes(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
input []byte
|
||||||
|
expected []byte
|
||||||
|
}{
|
||||||
|
"localConfigUnset": {
|
||||||
|
input: []byte(`apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie
|
||||||
|
`),
|
||||||
|
expected: []byte(`apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
"localConfigSet": {
|
||||||
|
input: []byte(`apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie-skip
|
||||||
|
annotations:
|
||||||
|
# this annotation causes the Resource to be ignored by kustomize
|
||||||
|
config.kubernetes.io/local-config: ""
|
||||||
|
`),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
"localConfigSetToTrue": {
|
||||||
|
input: []byte(`apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie-skip
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/local-config: "true"
|
||||||
|
`),
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
"localConfigSetToFalse": {
|
||||||
|
input: []byte(`apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/local-config: "false"
|
||||||
|
`),
|
||||||
|
expected: []byte(`apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/local-config: "false"
|
||||||
|
name: winnie
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
"localConfigMultiInput": {
|
||||||
|
input: []byte(`apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie-skip
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/local-config: "true"
|
||||||
|
`),
|
||||||
|
expected: []byte(`apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: winnie
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for n := range testCases {
|
||||||
|
tc := testCases[n]
|
||||||
|
t.Run(n, func(t *testing.T) {
|
||||||
|
nin, _ := kio.FromBytes(tc.input)
|
||||||
|
res, err := factory.DropLocalNodes(nin)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if tc.expected == nil {
|
||||||
|
assert.Equal(t, 0, len(res))
|
||||||
|
} else {
|
||||||
|
actual, _ := res[0].AsYAML()
|
||||||
|
assert.Equal(t, tc.expected, actual)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
60
api/resource/origin.go
Normal file
60
api/resource/origin.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package resource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/api/internal/git"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Origin retains information about where resources in the output
|
||||||
|
// of `kustomize build` originated from
|
||||||
|
type Origin struct {
|
||||||
|
// Path is the path to the resource, rooted from the directory upon
|
||||||
|
// which `kustomize build` was invoked
|
||||||
|
Path string
|
||||||
|
|
||||||
|
// Repo is the remote repository that the resource originated from if it is
|
||||||
|
// not from a local file
|
||||||
|
Repo string
|
||||||
|
|
||||||
|
// Ref is the ref of the remote repository that the resource originated from
|
||||||
|
// if it is not from a local file
|
||||||
|
Ref string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy returns a copy of origin
|
||||||
|
func (origin *Origin) Copy() Origin {
|
||||||
|
return *origin
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append returns a copy of origin with a path appended to it
|
||||||
|
func (origin *Origin) Append(path string) *Origin {
|
||||||
|
originCopy := origin.Copy()
|
||||||
|
repoSpec, err := git.NewRepoSpecFromUrl(path)
|
||||||
|
if err == nil {
|
||||||
|
originCopy.Repo = repoSpec.Host + repoSpec.OrgRepo
|
||||||
|
absPath := repoSpec.AbsPath()
|
||||||
|
path = absPath[strings.Index(absPath[1:], "/")+1:][1:]
|
||||||
|
originCopy.Path = ""
|
||||||
|
originCopy.Ref = repoSpec.Ref
|
||||||
|
}
|
||||||
|
originCopy.Path = filepath.Join(originCopy.Path, path)
|
||||||
|
return &originCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string version of origin
|
||||||
|
func (origin *Origin) String() string {
|
||||||
|
var anno string
|
||||||
|
anno = anno + "path: " + origin.Path + "\n"
|
||||||
|
if origin.Repo != "" {
|
||||||
|
anno = anno + "repo: " + origin.Repo + "\n"
|
||||||
|
}
|
||||||
|
if origin.Ref != "" {
|
||||||
|
anno = anno + "ref: " + origin.Ref + "\n"
|
||||||
|
}
|
||||||
|
return anno
|
||||||
|
}
|
||||||
83
api/resource/origin_test.go
Normal file
83
api/resource/origin_test.go
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package resource_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "sigs.k8s.io/kustomize/api/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOriginAppend(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
in *Origin
|
||||||
|
path string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
in: &Origin{
|
||||||
|
Path: "prod",
|
||||||
|
},
|
||||||
|
path: "service.yaml",
|
||||||
|
expected: `path: prod/service.yaml
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: &Origin{
|
||||||
|
Path: "overlay/prod",
|
||||||
|
},
|
||||||
|
path: "github.com/kubernetes-sigs/kustomize/examples/multibases/dev/",
|
||||||
|
expected: `path: examples/multibases/dev
|
||||||
|
repo: https://github.com/kubernetes-sigs/kustomize
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
actual := test.in.Append(test.path).String()
|
||||||
|
if actual != test.expected {
|
||||||
|
t.Fatalf("Expected %v, but got %v\n", test.expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOriginString(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
in *Origin
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
in: &Origin{
|
||||||
|
Path: "prod/service.yaml",
|
||||||
|
Repo: "github.com/kubernetes-sigs/kustomize/examples/multibases/dev/",
|
||||||
|
Ref: "v1.0.6",
|
||||||
|
},
|
||||||
|
expected: `path: prod/service.yaml
|
||||||
|
repo: github.com/kubernetes-sigs/kustomize/examples/multibases/dev/
|
||||||
|
ref: v1.0.6
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: &Origin{
|
||||||
|
Path: "prod/service.yaml",
|
||||||
|
Repo: "github.com/kubernetes-sigs/kustomize/examples/multibases/dev/",
|
||||||
|
},
|
||||||
|
expected: `path: prod/service.yaml
|
||||||
|
repo: github.com/kubernetes-sigs/kustomize/examples/multibases/dev/
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: &Origin{
|
||||||
|
Path: "prod/service.yaml",
|
||||||
|
},
|
||||||
|
expected: `path: prod/service.yaml
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
if test.in.String() != test.expected {
|
||||||
|
t.Fatalf("Expected %v, but got %v\n", test.expected, test.in.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,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/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
|
||||||
"sigs.k8s.io/kustomize/kyaml/resid"
|
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||||
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
|
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
@@ -22,8 +23,6 @@ import (
|
|||||||
// paired with metadata used by kustomize.
|
// paired with metadata used by kustomize.
|
||||||
type Resource struct {
|
type Resource struct {
|
||||||
kyaml.RNode
|
kyaml.RNode
|
||||||
options *types.GenArgs
|
|
||||||
refBy []resid.ResId
|
|
||||||
refVarNames []string
|
refVarNames []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,6 +34,16 @@ var BuildAnnotations = []string{
|
|||||||
utils.BuildAnnotationPreviousNamespaces,
|
utils.BuildAnnotationPreviousNamespaces,
|
||||||
utils.BuildAnnotationAllowNameChange,
|
utils.BuildAnnotationAllowNameChange,
|
||||||
utils.BuildAnnotationAllowKindChange,
|
utils.BuildAnnotationAllowKindChange,
|
||||||
|
utils.BuildAnnotationsRefBy,
|
||||||
|
utils.BuildAnnotationsGenBehavior,
|
||||||
|
utils.BuildAnnotationsGenAddHashSuffix,
|
||||||
|
|
||||||
|
kioutil.PathAnnotation,
|
||||||
|
kioutil.IndexAnnotation,
|
||||||
|
kioutil.SeqIndentAnnotation,
|
||||||
|
|
||||||
|
kioutil.LegacyPathAnnotation,
|
||||||
|
kioutil.LegacyIndexAnnotation,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) ResetRNode(incoming *Resource) {
|
func (r *Resource) ResetRNode(incoming *Resource) {
|
||||||
@@ -80,6 +89,8 @@ func (r *Resource) DeepCopy() *Resource {
|
|||||||
// CopyMergeMetaDataFieldsFrom copies everything but the non-metadata in
|
// CopyMergeMetaDataFieldsFrom copies everything but the non-metadata in
|
||||||
// the resource.
|
// the resource.
|
||||||
// TODO: move to RNode, use GetMeta to improve performance.
|
// TODO: move to RNode, use GetMeta to improve performance.
|
||||||
|
// TODO: make a version of mergeStringMaps that is build-annotation aware
|
||||||
|
// to avoid repeatedly setting refby and genargs annotations
|
||||||
// Must remove the kustomize bit at the end.
|
// Must remove the kustomize bit at the end.
|
||||||
func (r *Resource) CopyMergeMetaDataFieldsFrom(other *Resource) error {
|
func (r *Resource) CopyMergeMetaDataFieldsFrom(other *Resource) error {
|
||||||
if err := r.SetLabels(
|
if err := r.SetLabels(
|
||||||
@@ -87,7 +98,7 @@ func (r *Resource) CopyMergeMetaDataFieldsFrom(other *Resource) error {
|
|||||||
return fmt.Errorf("copyMerge cannot set labels - %w", err)
|
return fmt.Errorf("copyMerge cannot set labels - %w", err)
|
||||||
}
|
}
|
||||||
if err := r.SetAnnotations(
|
if err := r.SetAnnotations(
|
||||||
mergeStringMaps(other.GetAnnotations(), r.GetAnnotations())); err != nil {
|
mergeStringMapsWithBuildAnnotations(other.GetAnnotations(), r.GetAnnotations())); err != nil {
|
||||||
return fmt.Errorf("copyMerge cannot set annotations - %w", err)
|
return fmt.Errorf("copyMerge cannot set annotations - %w", err)
|
||||||
}
|
}
|
||||||
if err := r.SetName(other.GetName()); err != nil {
|
if err := r.SetName(other.GetName()); err != nil {
|
||||||
@@ -101,8 +112,6 @@ func (r *Resource) CopyMergeMetaDataFieldsFrom(other *Resource) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) copyKustomizeSpecificFields(other *Resource) {
|
func (r *Resource) copyKustomizeSpecificFields(other *Resource) {
|
||||||
r.options = other.options
|
|
||||||
r.refBy = other.copyRefBy()
|
|
||||||
r.refVarNames = copyStringSlice(other.refVarNames)
|
r.refVarNames = copyStringSlice(other.refVarNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,10 +153,10 @@ func (r *Resource) ErrIfNotEquals(o *Resource) error {
|
|||||||
func (r *Resource) ReferencesEqual(other *Resource) bool {
|
func (r *Resource) ReferencesEqual(other *Resource) bool {
|
||||||
setSelf := make(map[resid.ResId]bool)
|
setSelf := make(map[resid.ResId]bool)
|
||||||
setOther := make(map[resid.ResId]bool)
|
setOther := make(map[resid.ResId]bool)
|
||||||
for _, ref := range other.refBy {
|
for _, ref := range other.GetRefBy() {
|
||||||
setOther[ref] = true
|
setOther[ref] = true
|
||||||
}
|
}
|
||||||
for _, ref := range r.refBy {
|
for _, ref := range r.GetRefBy() {
|
||||||
if _, ok := setOther[ref]; !ok {
|
if _, ok := setOther[ref]; !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -156,15 +165,6 @@ func (r *Resource) ReferencesEqual(other *Resource) bool {
|
|||||||
return len(setSelf) == len(setOther)
|
return len(setSelf) == len(setOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) copyRefBy() []resid.ResId {
|
|
||||||
if r.refBy == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
s := make([]resid.ResId, len(r.refBy))
|
|
||||||
copy(s, r.refBy)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyStringSlice(s []string) []string {
|
func copyStringSlice(s []string) []string {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -250,41 +250,45 @@ func (r *Resource) setPreviousId(ns string, n string, k string) *Resource {
|
|||||||
|
|
||||||
// AllowNameChange allows name changes to the resource.
|
// AllowNameChange allows name changes to the resource.
|
||||||
func (r *Resource) AllowNameChange() {
|
func (r *Resource) AllowNameChange() {
|
||||||
annotations := r.GetAnnotations()
|
r.enable(utils.BuildAnnotationAllowNameChange)
|
||||||
annotations[utils.BuildAnnotationAllowNameChange] = utils.Allowed
|
|
||||||
if err := r.SetAnnotations(annotations); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NameChangeAllowed checks if a patch resource is allowed to change another resource's name.
|
||||||
func (r *Resource) NameChangeAllowed() bool {
|
func (r *Resource) NameChangeAllowed() bool {
|
||||||
annotations := r.GetAnnotations()
|
return r.isEnabled(utils.BuildAnnotationAllowNameChange)
|
||||||
v, ok := annotations[utils.BuildAnnotationAllowNameChange]
|
|
||||||
return ok && v == utils.Allowed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllowKindChange allows kind changes to the resource.
|
// AllowKindChange allows kind changes to the resource.
|
||||||
func (r *Resource) AllowKindChange() {
|
func (r *Resource) AllowKindChange() {
|
||||||
|
r.enable(utils.BuildAnnotationAllowKindChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KindChangeAllowed checks if a patch resource is allowed to change another resource's kind.
|
||||||
|
func (r *Resource) KindChangeAllowed() bool {
|
||||||
|
return r.isEnabled(utils.BuildAnnotationAllowKindChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resource) isEnabled(annoKey string) bool {
|
||||||
annotations := r.GetAnnotations()
|
annotations := r.GetAnnotations()
|
||||||
annotations[utils.BuildAnnotationAllowKindChange] = utils.Allowed
|
v, ok := annotations[annoKey]
|
||||||
|
return ok && v == utils.Enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resource) enable(annoKey string) {
|
||||||
|
annotations := r.GetAnnotations()
|
||||||
|
annotations[annoKey] = utils.Enabled
|
||||||
if err := r.SetAnnotations(annotations); err != nil {
|
if err := r.SetAnnotations(annotations); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) KindChangeAllowed() bool {
|
|
||||||
annotations := r.GetAnnotations()
|
|
||||||
v, ok := annotations[utils.BuildAnnotationAllowKindChange]
|
|
||||||
return ok && v == utils.Allowed
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns resource as JSON.
|
// String returns resource as JSON.
|
||||||
func (r *Resource) String() string {
|
func (r *Resource) String() string {
|
||||||
bs, err := r.MarshalJSON()
|
bs, err := r.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "<" + err.Error() + ">"
|
return "<" + err.Error() + ">"
|
||||||
}
|
}
|
||||||
return strings.TrimSpace(string(bs)) + r.options.String()
|
return strings.TrimSpace(string(bs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsYAML returns the resource in Yaml form.
|
// AsYAML returns the resource in Yaml form.
|
||||||
@@ -306,20 +310,34 @@ func (r *Resource) MustYaml() string {
|
|||||||
return string(yml)
|
return string(yml)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOptions updates the generator options for the resource.
|
|
||||||
func (r *Resource) SetOptions(o *types.GenArgs) {
|
|
||||||
r.options = o
|
|
||||||
}
|
|
||||||
|
|
||||||
// Behavior returns the behavior for the resource.
|
// Behavior returns the behavior for the resource.
|
||||||
func (r *Resource) Behavior() types.GenerationBehavior {
|
func (r *Resource) Behavior() types.GenerationBehavior {
|
||||||
return r.options.Behavior()
|
annotations := r.GetAnnotations()
|
||||||
|
if v, ok := annotations[utils.BuildAnnotationsGenBehavior]; ok {
|
||||||
|
return types.NewGenerationBehavior(v)
|
||||||
|
}
|
||||||
|
return types.NewGenerationBehavior("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBehavior sets the behavior for the resource.
|
||||||
|
func (r *Resource) SetBehavior(behavior types.GenerationBehavior) {
|
||||||
|
annotations := r.GetAnnotations()
|
||||||
|
annotations[utils.BuildAnnotationsGenBehavior] = behavior.String()
|
||||||
|
if err := r.SetAnnotations(annotations); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeedHashSuffix returns true if a resource content
|
// NeedHashSuffix returns true if a resource content
|
||||||
// hash should be appended to the name of the resource.
|
// hash should be appended to the name of the resource.
|
||||||
func (r *Resource) NeedHashSuffix() bool {
|
func (r *Resource) NeedHashSuffix() bool {
|
||||||
return r.options != nil && r.options.ShouldAddHashSuffixToName()
|
return r.isEnabled(utils.BuildAnnotationsGenAddHashSuffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableHashSuffix marks the resource as needing a content
|
||||||
|
// hash to be appended to the name of the resource.
|
||||||
|
func (r *Resource) EnableHashSuffix() {
|
||||||
|
r.enable(utils.BuildAnnotationsGenAddHashSuffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OrgId returns the original, immutable ResId for the resource.
|
// OrgId returns the original, immutable ResId for the resource.
|
||||||
@@ -363,12 +381,18 @@ func (r *Resource) CurId() resid.ResId {
|
|||||||
|
|
||||||
// GetRefBy returns the ResIds that referred to current resource
|
// GetRefBy returns the ResIds that referred to current resource
|
||||||
func (r *Resource) GetRefBy() []resid.ResId {
|
func (r *Resource) GetRefBy() []resid.ResId {
|
||||||
return r.refBy
|
var resIds []resid.ResId
|
||||||
|
asStrings := r.getCsvAnnotation(utils.BuildAnnotationsRefBy)
|
||||||
|
for _, s := range asStrings {
|
||||||
|
resIds = append(resIds, resid.FromString(s))
|
||||||
|
}
|
||||||
|
return resIds
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendRefBy appends a ResId into the refBy list
|
// AppendRefBy appends a ResId into the refBy list
|
||||||
func (r *Resource) AppendRefBy(id resid.ResId) {
|
// Using any type except fmt.Stringer here results in a compilation error
|
||||||
r.refBy = append(r.refBy, id)
|
func (r *Resource) AppendRefBy(id fmt.Stringer) {
|
||||||
|
r.appendCsvAnnotation(utils.BuildAnnotationsRefBy, id.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRefVarNames returns vars that refer to current resource
|
// GetRefVarNames returns vars that refer to current resource
|
||||||
@@ -424,3 +448,17 @@ func mergeStringMaps(maps ...map[string]string) map[string]string {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeStringMapsWithBuildAnnotations(maps ...map[string]string) map[string]string {
|
||||||
|
result := mergeStringMaps(maps...)
|
||||||
|
for i := range BuildAnnotations {
|
||||||
|
if len(maps) > 0 {
|
||||||
|
if v, ok := maps[0][BuildAnnotations[i]]; ok {
|
||||||
|
result[BuildAnnotations[i]] = v
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(result, BuildAnnotations[i])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ var testConfigMap = factory.FromMap(
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const genArgOptions = "{nsfx:false,beh:unspecified}"
|
|
||||||
|
|
||||||
//nolint:gosec
|
//nolint:gosec
|
||||||
const configMapAsString = `{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie","namespace":"hundred-acre-wood"}}`
|
const configMapAsString = `{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie","namespace":"hundred-acre-wood"}}`
|
||||||
|
|
||||||
@@ -66,17 +64,15 @@ func TestResourceString(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
in: testConfigMap,
|
in: testConfigMap,
|
||||||
s: configMapAsString + genArgOptions,
|
s: configMapAsString,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
in: testDeployment,
|
in: testDeployment,
|
||||||
s: deploymentAsString + genArgOptions,
|
s: deploymentAsString,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
if test.in.String() != test.s {
|
assert.Equal(t, test.in.String(), test.s)
|
||||||
t.Fatalf("Expected %s == %s", test.in.String(), test.s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,6 +280,266 @@ spec:
|
|||||||
`, string(bytes))
|
`, string(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApplySmPatchShouldOutputListItemsInCorrectOrder(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
skip bool
|
||||||
|
patch string
|
||||||
|
expectedOutput string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Order should not change when patch has foo only",
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: foo
|
||||||
|
`,
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: foo
|
||||||
|
- name: bar
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Order changes when patch has bar only",
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: bar
|
||||||
|
`,
|
||||||
|
// This test records current behavior, but this behavior might be undesirable.
|
||||||
|
// If so, feel free to change the test to pass with some improved algorithm.
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: bar
|
||||||
|
- name: foo
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Order should not change and should include a new item at the beginning when patch has a new list item",
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: baz
|
||||||
|
`,
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: baz
|
||||||
|
- name: foo
|
||||||
|
- name: bar
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Order should not change when patch has foo and bar in same order",
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: foo
|
||||||
|
- name: bar
|
||||||
|
`,
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: foo
|
||||||
|
- name: bar
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Order should change when patch has foo and bar in different order",
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: bar
|
||||||
|
- name: foo
|
||||||
|
`,
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: bar
|
||||||
|
- name: foo
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
if tc.skip {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
resource, err := factory.FromBytes([]byte(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: foo
|
||||||
|
- name: bar
|
||||||
|
`))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
patch, err := factory.FromBytes([]byte(tc.patch))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, resource.ApplySmPatch(patch))
|
||||||
|
bytes, err := resource.AsYAML()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expectedOutput, string(bytes))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplySmPatchShouldOutputPrimitiveListItemsInCorrectOrder(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
skip bool
|
||||||
|
patch string
|
||||||
|
expectedOutput string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Order should not change when patch has foo only",
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
finalizers: ["foo"]
|
||||||
|
`,
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
finalizers:
|
||||||
|
- foo
|
||||||
|
- bar
|
||||||
|
name: test
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Order should not change when patch has bar only",
|
||||||
|
skip: true, // TODO: This test should pass but fails currently. Fix the problem and unskip this test
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
finalizers: ["bar"]
|
||||||
|
`,
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
finalizers:
|
||||||
|
- foo
|
||||||
|
- bar
|
||||||
|
name: test
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Order should not change and should include a new item at the beginning when patch has a new list item",
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
finalizers: ["baz"]
|
||||||
|
`,
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
finalizers:
|
||||||
|
- baz
|
||||||
|
- foo
|
||||||
|
- bar
|
||||||
|
name: test
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Order should not change when patch has foo and bar in same order",
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
finalizers: ["foo", "bar"]
|
||||||
|
`,
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
finalizers:
|
||||||
|
- foo
|
||||||
|
- bar
|
||||||
|
name: test
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Order should change when patch has foo and bar in different order",
|
||||||
|
patch: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
finalizers: ["bar", "foo"]
|
||||||
|
`,
|
||||||
|
expectedOutput: `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
finalizers:
|
||||||
|
- bar
|
||||||
|
- foo
|
||||||
|
name: test
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
if tc.skip {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
resource, err := factory.FromBytes([]byte(`
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
finalizers: ["foo", "bar"]
|
||||||
|
`))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
patch, err := factory.FromBytes([]byte(tc.patch))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, resource.ApplySmPatch(patch))
|
||||||
|
bytes, err := resource.AsYAML()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expectedOutput, string(bytes))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMergeDataMapFrom(t *testing.T) {
|
func TestMergeDataMapFrom(t *testing.T) {
|
||||||
resource, err := factory.FromBytes([]byte(`
|
resource, err := factory.FromBytes([]byte(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@@ -717,9 +973,9 @@ metadata:
|
|||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/previousKinds: Secret
|
internal.config.kubernetes.io/previousKinds: Secret
|
||||||
config.kubernetes.io/previousNames: oldName
|
internal.config.kubernetes.io/previousNames: oldName
|
||||||
config.kubernetes.io/previousNamespaces: default
|
internal.config.kubernetes.io/previousNamespaces: default
|
||||||
name: newName
|
name: newName
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
@@ -729,9 +985,9 @@ metadata:
|
|||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/previousKinds: Secret
|
internal.config.kubernetes.io/previousKinds: Secret
|
||||||
config.kubernetes.io/previousNames: oldName
|
internal.config.kubernetes.io/previousNames: oldName
|
||||||
config.kubernetes.io/previousNamespaces: default
|
internal.config.kubernetes.io/previousNamespaces: default
|
||||||
name: oldName2
|
name: oldName2
|
||||||
`,
|
`,
|
||||||
newName: "newName",
|
newName: "newName",
|
||||||
@@ -740,9 +996,9 @@ metadata:
|
|||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/previousKinds: Secret,Secret
|
internal.config.kubernetes.io/previousKinds: Secret,Secret
|
||||||
config.kubernetes.io/previousNames: oldName,oldName2
|
internal.config.kubernetes.io/previousNames: oldName,oldName2
|
||||||
config.kubernetes.io/previousNamespaces: default,default
|
internal.config.kubernetes.io/previousNamespaces: default,default
|
||||||
name: newName
|
name: newName
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
@@ -752,9 +1008,9 @@ metadata:
|
|||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/previousKinds: Secret
|
internal.config.kubernetes.io/previousKinds: Secret
|
||||||
config.kubernetes.io/previousNames: oldName
|
internal.config.kubernetes.io/previousNames: oldName
|
||||||
config.kubernetes.io/previousNamespaces: default
|
internal.config.kubernetes.io/previousNamespaces: default
|
||||||
name: oldName2
|
name: oldName2
|
||||||
namespace: oldNamespace
|
namespace: oldNamespace
|
||||||
`,
|
`,
|
||||||
@@ -764,9 +1020,9 @@ metadata:
|
|||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/previousKinds: Secret,Secret
|
internal.config.kubernetes.io/previousKinds: Secret,Secret
|
||||||
config.kubernetes.io/previousNames: oldName,oldName2
|
internal.config.kubernetes.io/previousNames: oldName,oldName2
|
||||||
config.kubernetes.io/previousNamespaces: default,oldNamespace
|
internal.config.kubernetes.io/previousNamespaces: default,oldNamespace
|
||||||
name: newName
|
name: newName
|
||||||
namespace: newNamespace
|
namespace: newNamespace
|
||||||
`,
|
`,
|
||||||
@@ -814,9 +1070,9 @@ metadata:
|
|||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/previousKinds: Secret
|
internal.config.kubernetes.io/previousKinds: Secret
|
||||||
config.kubernetes.io/previousNames: oldName
|
internal.config.kubernetes.io/previousNames: oldName
|
||||||
config.kubernetes.io/previousNamespaces: default
|
internal.config.kubernetes.io/previousNamespaces: default
|
||||||
name: newName
|
name: newName
|
||||||
`,
|
`,
|
||||||
expected: []resid.ResId{
|
expected: []resid.ResId{
|
||||||
@@ -833,9 +1089,9 @@ metadata:
|
|||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/previousKinds: Secret,Secret
|
internal.config.kubernetes.io/previousKinds: Secret,Secret
|
||||||
config.kubernetes.io/previousNames: oldName,oldName2
|
internal.config.kubernetes.io/previousNames: oldName,oldName2
|
||||||
config.kubernetes.io/previousNamespaces: default,oldNamespace
|
internal.config.kubernetes.io/previousNamespaces: default,oldNamespace
|
||||||
name: newName
|
name: newName
|
||||||
namespace: newNamespace
|
namespace: newNamespace
|
||||||
`,
|
`,
|
||||||
@@ -1133,3 +1389,41 @@ spec:
|
|||||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRefBy(t *testing.T) {
|
||||||
|
r, err := factory.FromBytes([]byte(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: clown
|
||||||
|
spec:
|
||||||
|
numReplicas: 1
|
||||||
|
`))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
r.AppendRefBy(resid.FromString("gr1_ver1_knd1|ns1|name1"))
|
||||||
|
assert.Equal(t, r.RNode.MustString(), `apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: clown
|
||||||
|
annotations:
|
||||||
|
internal.config.kubernetes.io/refBy: gr1_ver1_knd1|ns1|name1
|
||||||
|
spec:
|
||||||
|
numReplicas: 1
|
||||||
|
`)
|
||||||
|
assert.Equal(t, r.GetRefBy(), []resid.ResId{resid.FromString("gr1_ver1_knd1|ns1|name1")})
|
||||||
|
|
||||||
|
r.AppendRefBy(resid.FromString("gr2_ver2_knd2|ns2|name2"))
|
||||||
|
assert.Equal(t, r.RNode.MustString(), `apiVersion: v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: clown
|
||||||
|
annotations:
|
||||||
|
internal.config.kubernetes.io/refBy: gr1_ver1_knd1|ns1|name1,gr2_ver2_knd2|ns2|name2
|
||||||
|
spec:
|
||||||
|
numReplicas: 1
|
||||||
|
`)
|
||||||
|
assert.Equal(t, r.GetRefBy(), []resid.ResId{
|
||||||
|
resid.FromString("gr1_ver1_knd1|ns1|name1"),
|
||||||
|
resid.FromString("gr2_ver2_knd2|ns2|name2"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -148,6 +148,13 @@ func (th *HarnessEnhanced) ResetLoaderRoot(root string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (th *HarnessEnhanced) LoadAndRunGenerator(
|
func (th *HarnessEnhanced) LoadAndRunGenerator(
|
||||||
|
config string) resmap.ResMap {
|
||||||
|
rm := th.LoadAndRunGeneratorWithBuildAnnotations(config)
|
||||||
|
rm.RemoveBuildAnnotations()
|
||||||
|
return rm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (th *HarnessEnhanced) LoadAndRunGeneratorWithBuildAnnotations(
|
||||||
config string) resmap.ResMap {
|
config string) resmap.ResMap {
|
||||||
res, err := th.rf.RF().FromBytes([]byte(config))
|
res, err := th.rf.RF().FromBytes([]byte(config))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -162,7 +169,6 @@ func (th *HarnessEnhanced) LoadAndRunGenerator(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
th.t.Fatalf("generate err: %v", err)
|
th.t.Fatalf("generate err: %v", err)
|
||||||
}
|
}
|
||||||
rm.RemoveBuildAnnotations()
|
|
||||||
return rm
|
return rm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GenArgs is a facade over GeneratorArgs, exposing a few readonly properties.
|
|
||||||
type GenArgs struct {
|
|
||||||
args *GeneratorArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGenArgs returns a new instance of GenArgs.
|
|
||||||
func NewGenArgs(args *GeneratorArgs) *GenArgs {
|
|
||||||
return &GenArgs{args: args}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GenArgs) String() string {
|
|
||||||
if g == nil {
|
|
||||||
return "{nilGenArgs}"
|
|
||||||
}
|
|
||||||
return "{" +
|
|
||||||
strings.Join([]string{
|
|
||||||
"nsfx:" + strconv.FormatBool(g.ShouldAddHashSuffixToName()),
|
|
||||||
"beh:" + g.Behavior().String()},
|
|
||||||
",") +
|
|
||||||
"}"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShouldAddHashSuffixToName returns true if a resource
|
|
||||||
// content hash should be appended to the name of the resource.
|
|
||||||
func (g *GenArgs) ShouldAddHashSuffixToName() bool {
|
|
||||||
return g.args != nil &&
|
|
||||||
(g.args.Options == nil || !g.args.Options.DisableNameSuffixHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Behavior returns Behavior field of GeneratorArgs
|
|
||||||
func (g *GenArgs) Behavior() GenerationBehavior {
|
|
||||||
if g == nil || g.args == nil {
|
|
||||||
return BehaviorUnspecified
|
|
||||||
}
|
|
||||||
return NewGenerationBehavior(g.args.Behavior)
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
// Copyright 2019 The Kubernetes Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package types_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "sigs.k8s.io/kustomize/api/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGenArgs_String(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
ga *GenArgs
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
ga: nil,
|
|
||||||
expected: "{nilGenArgs}",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ga: &GenArgs{},
|
|
||||||
expected: "{nsfx:false,beh:unspecified}",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ga: NewGenArgs(
|
|
||||||
&GeneratorArgs{
|
|
||||||
Behavior: "merge",
|
|
||||||
Options: &GeneratorOptions{DisableNameSuffixHash: false},
|
|
||||||
}),
|
|
||||||
expected: "{nsfx:true,beh:merge}",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
if test.ga.String() != test.expected {
|
|
||||||
t.Fatalf("Expected '%s', got '%s'", test.expected, test.ga.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -161,6 +161,9 @@ type Kustomization struct {
|
|||||||
// Inventory appends an object that contains the record
|
// Inventory appends an object that contains the record
|
||||||
// of all other objects, which can be used in apply, prune and delete
|
// of all other objects, which can be used in apply, prune and delete
|
||||||
Inventory *Inventory `json:"inventory,omitempty" yaml:"inventory,omitempty"`
|
Inventory *Inventory `json:"inventory,omitempty" yaml:"inventory,omitempty"`
|
||||||
|
|
||||||
|
// BuildMetadata is a list of strings used to toggle different build options
|
||||||
|
BuildMetadata []string `json:"buildMetadata,omitempty" yaml:"buildMetadata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FixKustomizationPostUnmarshalling fixes things
|
// FixKustomizationPostUnmarshalling fixes things
|
||||||
|
|||||||
@@ -57,4 +57,6 @@ type FnPluginLoadingOptions struct {
|
|||||||
Env []string
|
Env []string
|
||||||
// Run as uid and gid of the command executor
|
// Run as uid and gid of the command executor
|
||||||
AsCurrentUser bool
|
AsCurrentUser bool
|
||||||
|
// Run in this working directory
|
||||||
|
WorkingDir string
|
||||||
}
|
}
|
||||||
|
|||||||
6
cmd/config/OWNERS
Normal file
6
cmd/config/OWNERS
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# See https://github.com/kubernetes/community/blob/master/community-membership.md
|
||||||
|
approvers:
|
||||||
|
- kyaml-approvers
|
||||||
|
|
||||||
|
reviewers:
|
||||||
|
- kyaml-reviewers
|
||||||
@@ -327,49 +327,51 @@ A function SHOULD preserve comments when input serialization format is YAML.
|
|||||||
This allows for human authoring of configuration to coexist with changes made by
|
This allows for human authoring of configuration to coexist with changes made by
|
||||||
functions.
|
functions.
|
||||||
|
|
||||||
### Annotations
|
### Internal Annotations
|
||||||
|
|
||||||
The orchestrator annotates resources in the wire format with annotation prefix
|
For orchestration purposes, the orchestrator will use a set of annotations,
|
||||||
`config.kubernetes.io`. These annotations are not persisted when the
|
referred to as _internal annotations_, on resources in `Resources.items`. These
|
||||||
orchestrator writes the resources to the filesystem. The orchestrator sets this
|
annotations are not persisted to resource manifests on the filesystem: The
|
||||||
annotation when reading files from the local filesystem and removes the
|
orchestrator sets this annotation when reading files from the local filesystem
|
||||||
annotation when writing the output of functions back to the filesystem.
|
and removes the annotation when writing the output of functions back to the
|
||||||
|
filesystem.
|
||||||
|
|
||||||
In general, a function MUST NOT modify these annotations except the ones
|
Annotation prefix `internal.config.kubernetes.io` is reserved for use for
|
||||||
explicitly listed below.
|
internal annotations. In general, a function MUST NOT modify these annotations with
|
||||||
|
the exception of the specific annotations listed below. This enables orchestrators to add additional internal annotations, without requiring changes to existing functions.
|
||||||
|
|
||||||
#### `config.kubernetes.io/path`
|
#### `internal.config.kubernetes.io/path`
|
||||||
|
|
||||||
Records the slash-delimited, OS-agnostic, relative file path to a resource. The
|
Records the slash-delimited, OS-agnostic, relative file path to a resource. The
|
||||||
path is relative to a fix location on the filesystem. Different orchestrator
|
path is relative to a fix location on the filesystem. Different orchestrator
|
||||||
implementations can choose different fixed points.
|
implementations can choose different fixed points.
|
||||||
|
|
||||||
A function SHOULD NOT modify this annotation.
|
A function SHOULD NOT modify these annotations.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/path: "relative/file/path.yaml"
|
internal.config.kubernetes.io/path: "relative/file/path.yaml"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `config.kubernetes.io/index`
|
#### `internal.config.kubernetes.io/index`
|
||||||
|
|
||||||
Records the index of a Resource in file. In a multi-object YAML file, resources
|
Records the index of a Resource in file. In a multi-object YAML file, resources
|
||||||
are separated by three dashes (`---`), and the index represents the position of
|
are separated by three dashes (`---`), and the index represents the position of
|
||||||
the Resource starting from zero. When this annotation is not specified, it
|
the Resource starting from zero. When this annotation is not specified, it
|
||||||
implies a value of `0`.
|
implies a value of `0`.
|
||||||
|
|
||||||
A function SHOULD NOT modify this annotation.
|
A function SHOULD NOT modify these annotations.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/path: "relative/file/path.yaml"
|
internal.config.kubernetes.io/path: "relative/file/path.yaml"
|
||||||
config.kubernetes.io/index: 2
|
internal.config.kubernetes.io/index: 2
|
||||||
```
|
```
|
||||||
|
|
||||||
This represents the third resource in the file.
|
This represents the third resource in the file.
|
||||||
|
|||||||
11
cmd/config/docs/api-conventions/manifest-annotations.md
Normal file
11
cmd/config/docs/api-conventions/manifest-annotations.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Manifest Annotations
|
||||||
|
|
||||||
|
This document lists the annotations that can be declared in resource manifests.
|
||||||
|
|
||||||
|
### `config.kubernetes.io/local-config`
|
||||||
|
|
||||||
|
A value of `"true"` for this annotation declares that the resource is only consumed by
|
||||||
|
client-side tooling and should not be applied to the API server.
|
||||||
|
|
||||||
|
A value of `"false"` can be used to declare that a resource should be applied to
|
||||||
|
the API server even when it is assumed to be local.
|
||||||
@@ -16,5 +16,5 @@ require (
|
|||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1
|
gopkg.in/inf.v0 v0.9.1
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e
|
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0
|
sigs.k8s.io/kustomize/kyaml v0.12.0
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -245,7 +245,8 @@ k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
|
|||||||
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.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA=
|
sigs.k8s.io/kustomize/kyaml v0.12.0 h1:k08l8SLwnKa/eXXB5GW2/OnEc/4gJF90VDFebsOwqw4=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM=
|
sigs.k8s.io/kustomize/kyaml v0.12.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E=
|
||||||
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/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||||
|
|||||||
@@ -21,12 +21,13 @@ import (
|
|||||||
func NewAnnotateRunner(parent string) *AnnotateRunner {
|
func NewAnnotateRunner(parent string) *AnnotateRunner {
|
||||||
r := &AnnotateRunner{}
|
r := &AnnotateRunner{}
|
||||||
c := &cobra.Command{
|
c := &cobra.Command{
|
||||||
Use: "annotate [DIR]",
|
Use: "annotate [DIR]",
|
||||||
Args: cobra.MaximumNArgs(1),
|
Args: cobra.MaximumNArgs(1),
|
||||||
Short: commands.AnnotateShort,
|
Short: commands.AnnotateShort,
|
||||||
Long: commands.AnnotateLong,
|
Long: commands.AnnotateLong,
|
||||||
Example: commands.AnnotateExamples,
|
Example: commands.AnnotateExamples,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
Deprecated: "use the `commonAnnotations` field in your kustomization file.",
|
||||||
}
|
}
|
||||||
runner.FixDocs(parent, c)
|
runner.FixDocs(parent, c)
|
||||||
r.Command = c
|
r.Command = c
|
||||||
|
|||||||
@@ -164,6 +164,8 @@ metadata:
|
|||||||
a: 'b'
|
a: 'b'
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
---
|
---
|
||||||
@@ -175,6 +177,8 @@ metadata:
|
|||||||
a: 'b'
|
a: 'b'
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -191,6 +195,8 @@ metadata:
|
|||||||
a: 'b'
|
a: 'b'
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: bar
|
namespace: bar
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -206,6 +212,8 @@ metadata:
|
|||||||
a: 'b'
|
a: 'b'
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: foo
|
namespace: foo
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -222,6 +230,8 @@ metadata:
|
|||||||
c: 'd'
|
c: 'd'
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
---
|
---
|
||||||
@@ -234,6 +244,8 @@ metadata:
|
|||||||
c: 'd'
|
c: 'd'
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -251,6 +263,8 @@ metadata:
|
|||||||
c: 'd'
|
c: 'd'
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: bar
|
namespace: bar
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -267,6 +281,8 @@ metadata:
|
|||||||
c: 'd'
|
c: 'd'
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: foo
|
namespace: foo
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -281,6 +297,8 @@ metadata:
|
|||||||
app: nginx2
|
app: nginx2
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
---
|
---
|
||||||
@@ -292,6 +310,8 @@ metadata:
|
|||||||
a: 'b'
|
a: 'b'
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -307,6 +327,8 @@ metadata:
|
|||||||
config.kubernetes.io/local-config: "true"
|
config.kubernetes.io/local-config: "true"
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: bar
|
namespace: bar
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -321,6 +343,8 @@ metadata:
|
|||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: foo
|
namespace: foo
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -335,6 +359,8 @@ metadata:
|
|||||||
app: nginx2
|
app: nginx2
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
---
|
---
|
||||||
@@ -345,6 +371,8 @@ metadata:
|
|||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -361,6 +389,8 @@ metadata:
|
|||||||
a: 'b'
|
a: 'b'
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: bar
|
namespace: bar
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -375,6 +405,8 @@ metadata:
|
|||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: foo
|
namespace: foo
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -389,6 +421,8 @@ metadata:
|
|||||||
app: nginx2
|
app: nginx2
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
---
|
---
|
||||||
@@ -399,6 +433,8 @@ metadata:
|
|||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -414,6 +450,8 @@ metadata:
|
|||||||
config.kubernetes.io/local-config: "true"
|
config.kubernetes.io/local-config: "true"
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: bar
|
namespace: bar
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -429,6 +467,8 @@ metadata:
|
|||||||
a: 'b'
|
a: 'b'
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: foo
|
namespace: foo
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -443,6 +483,8 @@ metadata:
|
|||||||
app: nginx2
|
app: nginx2
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
---
|
---
|
||||||
@@ -453,6 +495,8 @@ metadata:
|
|||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -469,6 +513,8 @@ metadata:
|
|||||||
a: 'b'
|
a: 'b'
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: bar
|
namespace: bar
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -483,6 +529,8 @@ metadata:
|
|||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
namespace: foo
|
namespace: foo
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
@@ -559,7 +607,7 @@ added annotations in the package
|
|||||||
|
|
||||||
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
||||||
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
||||||
if !assert.Equal(t, expectedNormalized, actualNormalized) {
|
if !assert.Contains(t, actualNormalized, expectedNormalized) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -182,7 +183,7 @@ func (r *CatRunner) out(w io.Writer) ([]kio.Writer, error) {
|
|||||||
|
|
||||||
// remove this annotation explicitly, the ByteWriter won't clear it by
|
// remove this annotation explicitly, the ByteWriter won't clear it by
|
||||||
// default because it doesn't set it
|
// default because it doesn't set it
|
||||||
clear := []string{"config.kubernetes.io/path"}
|
clear := []string{kioutil.LegacyPathAnnotation, kioutil.PathAnnotation}
|
||||||
if r.KeepAnnotations {
|
if r.KeepAnnotations {
|
||||||
clear = nil
|
clear = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ func NewCreateSetterRunner(parent string) *CreateSetterRunner {
|
|||||||
Example: commands.CreateSetterExamples,
|
Example: commands.CreateSetterExamples,
|
||||||
PreRunE: r.preRunE,
|
PreRunE: r.preRunE,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
Deprecated: "setter commands will no longer be available in kustomize v5.\n" +
|
||||||
|
"See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.",
|
||||||
}
|
}
|
||||||
set.Flags().StringVar(&r.FieldValue, "value", "",
|
set.Flags().StringVar(&r.FieldValue, "value", "",
|
||||||
"optional flag, alternative to specifying the value as an argument. e.g. used to specify values that start with '-'")
|
"optional flag, alternative to specifying the value as an argument. e.g. used to specify values that start with '-'")
|
||||||
|
|||||||
@@ -869,7 +869,7 @@ setter with name "namespace" already exists, if you want to modify it, please de
|
|||||||
|
|
||||||
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
||||||
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
||||||
if !assert.Equal(t, expectedNormalized, actualNormalized) {
|
if !assert.Contains(t, actualNormalized, expectedNormalized) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ func NewCreateSubstitutionRunner(parent string) *CreateSubstitutionRunner {
|
|||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
PreRun: r.preRun,
|
PreRun: r.preRun,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
Deprecated: "imperative substitutions will no longer be available in kustomize v5.\n" +
|
||||||
|
"See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.",
|
||||||
}
|
}
|
||||||
cs.Flags().StringVar(&r.CreateSubstitution.FieldName, "field", "",
|
cs.Flags().StringVar(&r.CreateSubstitution.FieldName, "field", "",
|
||||||
"name of the field to set -- e.g. --field image")
|
"name of the field to set -- e.g. --field image")
|
||||||
|
|||||||
@@ -506,7 +506,7 @@ created substitution "image-tag"`,
|
|||||||
|
|
||||||
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
||||||
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
||||||
if !assert.Equal(t, strings.TrimSpace(expectedNormalized), strings.TrimSpace(actualNormalized)) {
|
if !assert.Contains(t, strings.TrimSpace(actualNormalized), strings.TrimSpace(expectedNormalized)) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ func GetInitRunner(name string) *InitRunner {
|
|||||||
Long: commands.InitLong,
|
Long: commands.InitLong,
|
||||||
Example: commands.InitExamples,
|
Example: commands.InitExamples,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
Deprecated: "setter commands and substitutions will no longer be available in kustomize v5.\n" +
|
||||||
|
"See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.",
|
||||||
}
|
}
|
||||||
runner.FixDocs(name, c)
|
runner.FixDocs(name, c)
|
||||||
r.Command = c
|
r.Command = c
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ func NewListSettersRunner(parent string) *ListSettersRunner {
|
|||||||
Example: commands.ListSettersExamples,
|
Example: commands.ListSettersExamples,
|
||||||
PreRunE: r.preRunE,
|
PreRunE: r.preRunE,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
Deprecated: "setter commands will no longer be available in kustomize v5.\n" +
|
||||||
|
"See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.",
|
||||||
}
|
}
|
||||||
c.Flags().BoolVar(&r.Markdown, "markdown", false,
|
c.Flags().BoolVar(&r.Markdown, "markdown", false,
|
||||||
"output as github markdown")
|
"output as github markdown")
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ test/testdata/dataset-with-setters/mysql/
|
|||||||
// normalize path format for windows
|
// normalize path format for windows
|
||||||
actualNormalized := strings.Replace(actual.String(), "\\", "/", -1)
|
actualNormalized := strings.Replace(actual.String(), "\\", "/", -1)
|
||||||
|
|
||||||
if !assert.Equal(t, strings.TrimSpace(test.expected), strings.TrimSpace(actualNormalized)) {
|
if !assert.Contains(t, strings.TrimSpace(actualNormalized), strings.TrimSpace(test.expected)) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ func NewSetRunner(parent string) *SetRunner {
|
|||||||
Example: commands.SetExamples,
|
Example: commands.SetExamples,
|
||||||
PreRunE: r.preRunE,
|
PreRunE: r.preRunE,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
Deprecated: "setter commands will no longer be available in kustomize v5.\n" +
|
||||||
|
"See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.",
|
||||||
}
|
}
|
||||||
runner.FixDocs(parent, c)
|
runner.FixDocs(parent, c)
|
||||||
r.Command = c
|
r.Command = c
|
||||||
|
|||||||
@@ -1137,7 +1137,7 @@ set 1 field(s) of setter "namespace" to value "otherspace"
|
|||||||
expectedNormalized := strings.Replace(
|
expectedNormalized := strings.Replace(
|
||||||
strings.Replace(expected, "\\", "/", -1),
|
strings.Replace(expected, "\\", "/", -1),
|
||||||
"//", "/", -1)
|
"//", "/", -1)
|
||||||
if !assert.Equal(t, strings.TrimSpace(expectedNormalized), strings.TrimSpace(actualNormalized)) {
|
if !assert.Contains(t, strings.TrimSpace(actualNormalized), strings.TrimSpace(expectedNormalized)) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package commands
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -47,6 +48,7 @@ Environment Variables:
|
|||||||
|
|
||||||
`,
|
`,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
PreRunE: r.preRunE,
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true},
|
FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true},
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
@@ -78,6 +80,12 @@ func WrapCommand() *cobra.Command {
|
|||||||
return GetWrapRunner().Command
|
return GetWrapRunner().Command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *WrapRunner) preRunE(_ *cobra.Command, _ []string) error {
|
||||||
|
_, err := fmt.Fprintln(os.Stderr, `Command "wrap" is deprecated, this will no longer be available in kustomize v5.
|
||||||
|
See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.`)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *WrapRunner) runE(c *cobra.Command, args []string) error {
|
func (r *WrapRunner) runE(c *cobra.Command, args []string) error {
|
||||||
if r.getEnv == nil {
|
if r.getEnv == nil {
|
||||||
r.getEnv = os.Getenv
|
r.getEnv = os.Getenv
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'config/test_deployment.yaml'
|
config.kubernetes.io/path: 'config/test_deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'config/test_deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 11
|
replicas: 11
|
||||||
selector:
|
selector:
|
||||||
@@ -112,6 +114,8 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'config/test_service.yaml'
|
config.kubernetes.io/path: 'config/test_service.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'config/test_service.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
name: test
|
name: test
|
||||||
@@ -136,6 +140,8 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'config/test_deployment.yaml'
|
config.kubernetes.io/path: 'config/test_deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'config/test_deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 11
|
replicas: 11
|
||||||
selector:
|
selector:
|
||||||
@@ -164,6 +170,8 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'config/test_service.yaml'
|
config.kubernetes.io/path: 'config/test_service.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'config/test_service.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
name: test
|
name: test
|
||||||
@@ -186,6 +194,8 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'config/mysql-deployment_deployment.yaml'
|
config.kubernetes.io/path: 'config/mysql-deployment_deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'config/mysql-deployment_deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
template:
|
template:
|
||||||
@@ -201,6 +211,8 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'config/nosetters-deployment_deployment.yaml'
|
config.kubernetes.io/path: 'config/nosetters-deployment_deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'config/nosetters-deployment_deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 4
|
replicas: 4
|
||||||
template:
|
template:
|
||||||
@@ -216,6 +228,8 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'config/storage-deployment_deployment.yaml'
|
config.kubernetes.io/path: 'config/storage-deployment_deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'config/storage-deployment_deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 4
|
replicas: 4
|
||||||
template:
|
template:
|
||||||
@@ -233,6 +247,8 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'config/test_deployment.yaml'
|
config.kubernetes.io/path: 'config/test_deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'config/test_deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 11
|
replicas: 11
|
||||||
selector:
|
selector:
|
||||||
@@ -264,6 +280,8 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'config/test_service.yaml'
|
config.kubernetes.io/path: 'config/test_service.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'config/test_service.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
name: test
|
name: test
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ $ kyaml cat pkg/ --function-config config.yaml --wrap-kind ResourceList | kyaml
|
|||||||
|
|
||||||
`,
|
`,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
PreRunE: r.preRunE,
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true},
|
FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true},
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
@@ -84,6 +85,12 @@ func XArgsCommand() *cobra.Command {
|
|||||||
return GetXArgsRunner().Command
|
return GetXArgsRunner().Command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *XArgsRunner) preRunE(_ *cobra.Command, _ []string) error {
|
||||||
|
_, err := fmt.Fprintln(os.Stderr, `Command "xargs" is deprecated, this will no longer be available in kustomize v5.
|
||||||
|
See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.`)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *XArgsRunner) runE(c *cobra.Command, _ []string) error {
|
func (r *XArgsRunner) runE(c *cobra.Command, _ []string) error {
|
||||||
if len(r.Args) == 0 {
|
if len(r.Args) == 0 {
|
||||||
r.Args = os.Args
|
r.Args = os.Args
|
||||||
|
|||||||
@@ -542,13 +542,13 @@ kind: Input
|
|||||||
metadata:
|
metadata:
|
||||||
name: foo
|
name: foo
|
||||||
annotations:
|
annotations:
|
||||||
a-bool-value: true
|
|
||||||
a-int-value: 2
|
|
||||||
a-string-value: a
|
|
||||||
config.kubernetes.io/function: |
|
config.kubernetes.io/function: |
|
||||||
starlark:
|
starlark:
|
||||||
path: script.star
|
path: script.star
|
||||||
name: fn
|
name: fn
|
||||||
|
a-bool-value: true
|
||||||
|
a-int-value: 2
|
||||||
|
a-string-value: a
|
||||||
data:
|
data:
|
||||||
boolValue: true
|
boolValue: true
|
||||||
intValue: 2
|
intValue: 2
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ func GetFmtRunner(name string) *FmtRunner {
|
|||||||
Example: commands.FmtExamples,
|
Example: commands.FmtExamples,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
PreRunE: r.preRunE,
|
PreRunE: r.preRunE,
|
||||||
|
Deprecated: "imperative formatting will no longer be available in kustomize v5.\n" +
|
||||||
|
"Declare a formatting transformer in your kustomization instead.",
|
||||||
}
|
}
|
||||||
runner.FixDocs(name, c)
|
runner.FixDocs(name, c)
|
||||||
c.Flags().StringVar(&r.FilenamePattern, "pattern", filters.DefaultFilenamePattern,
|
c.Flags().StringVar(&r.FilenamePattern, "pattern", filters.DefaultFilenamePattern,
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func TestFmtCommand_stdin(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// verify the output
|
// verify the output
|
||||||
assert.Equal(t, string(testyaml.FormattedYaml1), out.String())
|
assert.Contains(t, out.String(), string(testyaml.FormattedYaml1))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestCmd_filesAndstdin verifies that if both files and stdin input are provided, only
|
// TestCmd_filesAndstdin verifies that if both files and stdin input are provided, only
|
||||||
@@ -238,7 +238,7 @@ formatted resource files in the package
|
|||||||
|
|
||||||
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1)
|
||||||
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
expectedNormalized := strings.Replace(expected, "\\", "/", -1)
|
||||||
if !assert.Equal(t, strings.TrimSpace(expectedNormalized), strings.TrimSpace(actualNormalized)) {
|
if !assert.Contains(t, strings.TrimSpace(actualNormalized), strings.TrimSpace(expectedNormalized)) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ metadata:
|
|||||||
app: nginx2
|
app: nginx2
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
---
|
---
|
||||||
@@ -89,6 +91,8 @@ metadata:
|
|||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -146,6 +150,7 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
app: nginx2
|
app: nginx2
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
---
|
---
|
||||||
@@ -155,6 +160,7 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -295,6 +301,8 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'deployment.yaml'
|
config.kubernetes.io/path: 'deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
template:
|
template:
|
||||||
@@ -314,6 +322,8 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'deployment.yaml'
|
config.kubernetes.io/path: 'deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 4
|
replicas: 4
|
||||||
template:
|
template:
|
||||||
@@ -339,6 +349,8 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'deployment.yaml'
|
config.kubernetes.io/path: 'deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
template:
|
template:
|
||||||
@@ -364,6 +376,8 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'deployment.yaml'
|
config.kubernetes.io/path: 'deployment.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'deployment.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 4
|
replicas: 4
|
||||||
template:
|
template:
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ kind: Krmfile
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !assert.Equal(t, "", b.String()) {
|
if !assert.Equal(t, `Command "init" is deprecated, setter commands and substitutions will no longer be available in kustomize v5.
|
||||||
|
See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.
|
||||||
|
`, b.String()) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +80,9 @@ kind: Krmfile
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !assert.Equal(t, "", b.String()) {
|
if !assert.Equal(t, `Command "init" is deprecated, setter commands and substitutions will no longer be available in kustomize v5.
|
||||||
|
See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.
|
||||||
|
`, b.String()) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ func GetMergeRunner(name string) *MergeRunner {
|
|||||||
Long: commands.MergeLong,
|
Long: commands.MergeLong,
|
||||||
Example: commands.MergeExamples,
|
Example: commands.MergeExamples,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
Deprecated: "this will no longer be available in kustomize v5.\n" +
|
||||||
|
"See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.",
|
||||||
}
|
}
|
||||||
runner.FixDocs(name, c)
|
runner.FixDocs(name, c)
|
||||||
r.Command = c
|
r.Command = c
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ func GetMerge3Runner(name string) *Merge3Runner {
|
|||||||
Long: commands.Merge3Long,
|
Long: commands.Merge3Long,
|
||||||
Example: commands.Merge3Examples,
|
Example: commands.Merge3Examples,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
Deprecated: "this will no longer be available in kustomize v5.\n" +
|
||||||
|
"See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.",
|
||||||
}
|
}
|
||||||
runner.FixDocs(name, c)
|
runner.FixDocs(name, c)
|
||||||
c.Flags().StringVar(&r.ancestor, "ancestor", "",
|
c.Flags().StringVar(&r.ancestor, "ancestor", "",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package commands
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -73,6 +74,7 @@ func GetRunFnRunner(name string) *RunFnRunner {
|
|||||||
"a list of environment variables to be used by functions")
|
"a list of environment variables to be used by functions")
|
||||||
r.Command.Flags().BoolVar(
|
r.Command.Flags().BoolVar(
|
||||||
&r.AsCurrentUser, "as-current-user", false, "use the uid and gid of the command executor to run the function in the container")
|
&r.AsCurrentUser, "as-current-user", false, "use the uid and gid of the command executor to run the function in the container")
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,6 +304,11 @@ func (r *RunFnRunner) preRunE(c *cobra.Command, args []string) error {
|
|||||||
// parse mounts to set storageMounts
|
// parse mounts to set storageMounts
|
||||||
storageMounts := toStorageMounts(r.Mounts)
|
storageMounts := toStorageMounts(r.Mounts)
|
||||||
|
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
r.RunFns = runfn.RunFns{
|
r.RunFns = runfn.RunFns{
|
||||||
FunctionPaths: r.FnPaths,
|
FunctionPaths: r.FnPaths,
|
||||||
GlobalScope: r.GlobalScope,
|
GlobalScope: r.GlobalScope,
|
||||||
@@ -317,6 +324,7 @@ func (r *RunFnRunner) preRunE(c *cobra.Command, args []string) error {
|
|||||||
LogSteps: r.LogSteps,
|
LogSteps: r.LogSteps,
|
||||||
Env: r.Env,
|
Env: r.Env,
|
||||||
AsCurrentUser: r.AsCurrentUser,
|
AsCurrentUser: r.AsCurrentUser,
|
||||||
|
WorkingDir: wd,
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't consider args for the function
|
// don't consider args for the function
|
||||||
|
|||||||
@@ -11,13 +11,14 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/runfn"
|
"sigs.k8s.io/kustomize/kyaml/runfn"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestRunFnCommand_preRunE verifies that preRunE correctly parses the commandline
|
// TestRunFnCommand_preRunE verifies that preRunE correctly parses the commandline
|
||||||
// flags and arguments into the RunFns structure to be executed.
|
// flags and arguments into the RunFns structure to be executed.
|
||||||
func TestRunFnCommand_preRunE(t *testing.T) {
|
func TestRunFnCommand_preRunE(t *testing.T) {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
assert.NoError(t, err)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args []string
|
args []string
|
||||||
@@ -201,6 +202,7 @@ apiVersion: v1
|
|||||||
Path: "dir",
|
Path: "dir",
|
||||||
EnableStarlark: true,
|
EnableStarlark: true,
|
||||||
Env: []string{},
|
Env: []string{},
|
||||||
|
WorkingDir: wd,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -254,6 +256,7 @@ apiVersion: v1
|
|||||||
Path: "dir",
|
Path: "dir",
|
||||||
ResultsDir: "foo/",
|
ResultsDir: "foo/",
|
||||||
Env: []string{},
|
Env: []string{},
|
||||||
|
WorkingDir: wd,
|
||||||
},
|
},
|
||||||
expected: `
|
expected: `
|
||||||
metadata:
|
metadata:
|
||||||
@@ -286,9 +289,10 @@ apiVersion: v1
|
|||||||
args: []string{"run", "dir", "--log-steps"},
|
args: []string{"run", "dir", "--log-steps"},
|
||||||
path: "dir",
|
path: "dir",
|
||||||
expectedStruct: &runfn.RunFns{
|
expectedStruct: &runfn.RunFns{
|
||||||
Path: "dir",
|
Path: "dir",
|
||||||
LogSteps: true,
|
LogSteps: true,
|
||||||
Env: []string{},
|
Env: []string{},
|
||||||
|
WorkingDir: wd,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -296,8 +300,9 @@ apiVersion: v1
|
|||||||
args: []string{"run", "dir", "--env", "FOO=BAR", "-e", "BAR"},
|
args: []string{"run", "dir", "--env", "FOO=BAR", "-e", "BAR"},
|
||||||
path: "dir",
|
path: "dir",
|
||||||
expectedStruct: &runfn.RunFns{
|
expectedStruct: &runfn.RunFns{
|
||||||
Path: "dir",
|
Path: "dir",
|
||||||
Env: []string{"FOO=BAR", "BAR"},
|
Env: []string{"FOO=BAR", "BAR"},
|
||||||
|
WorkingDir: wd,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -308,6 +313,7 @@ apiVersion: v1
|
|||||||
Path: "dir",
|
Path: "dir",
|
||||||
AsCurrentUser: true,
|
AsCurrentUser: true,
|
||||||
Env: []string{},
|
Env: []string{},
|
||||||
|
WorkingDir: wd,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||||
@@ -20,6 +23,7 @@ func GetSinkRunner(name string) *SinkRunner {
|
|||||||
Long: commands.SinkLong,
|
Long: commands.SinkLong,
|
||||||
Example: commands.SinkExamples,
|
Example: commands.SinkExamples,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
PreRunE: r.preRunE,
|
||||||
Args: cobra.MaximumNArgs(1),
|
Args: cobra.MaximumNArgs(1),
|
||||||
}
|
}
|
||||||
runner.FixDocs(name, c)
|
runner.FixDocs(name, c)
|
||||||
@@ -36,6 +40,12 @@ type SinkRunner struct {
|
|||||||
Command *cobra.Command
|
Command *cobra.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *SinkRunner) preRunE(c *cobra.Command, args []string) error {
|
||||||
|
_, err := fmt.Fprintln(os.Stderr, `Command "sink" is deprecated, this will no longer be available in kustomize v5.
|
||||||
|
See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.`)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *SinkRunner) runE(c *cobra.Command, args []string) error {
|
func (r *SinkRunner) runE(c *cobra.Command, args []string) error {
|
||||||
var outputs []kio.Writer
|
var outputs []kio.Writer
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
@@ -43,7 +53,7 @@ func (r *SinkRunner) runE(c *cobra.Command, args []string) error {
|
|||||||
} else {
|
} else {
|
||||||
outputs = []kio.Writer{&kio.ByteWriter{
|
outputs = []kio.Writer{&kio.ByteWriter{
|
||||||
Writer: c.OutOrStdout(),
|
Writer: c.OutOrStdout(),
|
||||||
ClearAnnotations: []string{kioutil.PathAnnotation}},
|
ClearAnnotations: []string{kioutil.PathAnnotation, kioutil.LegacyPathAnnotation}},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package commands
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||||
@@ -22,6 +23,7 @@ func GetSourceRunner(name string) *SourceRunner {
|
|||||||
Long: commands.SourceLong,
|
Long: commands.SourceLong,
|
||||||
Example: commands.SourceExamples,
|
Example: commands.SourceExamples,
|
||||||
RunE: r.runE,
|
RunE: r.runE,
|
||||||
|
PreRunE: r.preRunE,
|
||||||
}
|
}
|
||||||
runner.FixDocs(name, c)
|
runner.FixDocs(name, c)
|
||||||
c.Flags().StringVar(&r.WrapKind, "wrap-kind", kio.ResourceListKind,
|
c.Flags().StringVar(&r.WrapKind, "wrap-kind", kio.ResourceListKind,
|
||||||
@@ -47,6 +49,12 @@ type SourceRunner struct {
|
|||||||
Command *cobra.Command
|
Command *cobra.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *SourceRunner) preRunE(c *cobra.Command, args []string) error {
|
||||||
|
_, err := fmt.Fprintln(os.Stderr, `Command "source" is deprecated, this will no longer be available in kustomize v5.
|
||||||
|
See discussion in https://github.com/kubernetes-sigs/kustomize/issues/3953.`)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *SourceRunner) runE(c *cobra.Command, args []string) error {
|
func (r *SourceRunner) runE(c *cobra.Command, args []string) error {
|
||||||
// if there is a function-config specified, emit it
|
// if there is a function-config specified, emit it
|
||||||
var functionConfig *yaml.RNode
|
var functionConfig *yaml.RNode
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ items:
|
|||||||
app: nginx2
|
app: nginx2
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
- kind: Service
|
- kind: Service
|
||||||
@@ -102,6 +104,8 @@ items:
|
|||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f1.yaml'
|
config.kubernetes.io/path: 'f1.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f1.yaml'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -116,6 +120,8 @@ items:
|
|||||||
config.kubernetes.io/local-config: "true"
|
config.kubernetes.io/local-config: "true"
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
- apiVersion: apps/v1
|
- apiVersion: apps/v1
|
||||||
@@ -128,6 +134,8 @@ items:
|
|||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
config.kubernetes.io/path: 'f2.yaml'
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/path: 'f2.yaml'
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
`, b.String()) {
|
`, b.String()) {
|
||||||
@@ -194,8 +202,8 @@ func TestSourceCommandJSON(t *testing.T) {
|
|||||||
if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1
|
if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1
|
||||||
kind: ResourceList
|
kind: ResourceList
|
||||||
items:
|
items:
|
||||||
- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", "annotations": {"app": "nginx2", config.kubernetes.io/index: '0', config.kubernetes.io/path: 'f1.json'}}, "spec": {"replicas": 1}}
|
- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", "annotations": {"app": "nginx2", config.kubernetes.io/index: '0', config.kubernetes.io/path: 'f1.json', internal.config.kubernetes.io/index: '0', internal.config.kubernetes.io/path: 'f1.json'}}, "spec": {"replicas": 1}}
|
||||||
- {"apiVersion": "v1", "kind": "Abstraction", "metadata": {"name": "foo", "annotations": {"config.kubernetes.io/function": "container:\n image: gcr.io/example/reconciler:v1\n", "config.kubernetes.io/local-config": "true", config.kubernetes.io/index: '0', config.kubernetes.io/path: 'f2.json'}}, "spec": {"replicas": 3}}
|
- {"apiVersion": "v1", "kind": "Abstraction", "metadata": {"name": "foo", "annotations": {"config.kubernetes.io/function": "container:\n image: gcr.io/example/reconciler:v1\n", "config.kubernetes.io/local-config": "true", config.kubernetes.io/index: '0', config.kubernetes.io/path: 'f2.json', internal.config.kubernetes.io/index: '0', internal.config.kubernetes.io/path: 'f2.json'}}, "spec": {"replicas": 3}}
|
||||||
`, b.String()) {
|
`, b.String()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -249,6 +257,7 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
app: nginx2
|
app: nginx2
|
||||||
config.kubernetes.io/index: '0'
|
config.kubernetes.io/index: '0'
|
||||||
|
internal.config.kubernetes.io/index: '0'
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
- kind: Service
|
- kind: Service
|
||||||
@@ -257,6 +266,7 @@ items:
|
|||||||
annotations:
|
annotations:
|
||||||
app: nginx
|
app: nginx
|
||||||
config.kubernetes.io/index: '1'
|
config.kubernetes.io/index: '1'
|
||||||
|
internal.config.kubernetes.io/index: '1'
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: nginx
|
app: nginx
|
||||||
@@ -302,7 +312,7 @@ func TestSourceCommandJSON_Stdin(t *testing.T) {
|
|||||||
if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1
|
if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1
|
||||||
kind: ResourceList
|
kind: ResourceList
|
||||||
items:
|
items:
|
||||||
- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", "annotations": {"app": "nginx2", config.kubernetes.io/index: '0'}}, "spec": {"replicas": 1}}
|
- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", "annotations": {"app": "nginx2", config.kubernetes.io/index: '0', internal.config.kubernetes.io/index: '0'}}, "spec": {"replicas": 1}}
|
||||||
`, out.String()) {
|
`, out.String()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,12 +278,13 @@ func (gr *Runner) CheckoutReleaseBranch(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
gr.comment("creating branch")
|
gr.comment("creating branch")
|
||||||
// The branch doesn't exist. Create it.
|
// The branch doesn't exist remotely. Create or reset it locally.
|
||||||
out, err := gr.run(noHarmDone, "checkout", "-b", branch)
|
out, err := gr.run(noHarmDone, "checkout", "-B", branch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !strings.Contains(out, "Switched to a new branch ") {
|
// Expected strings: "Switched to a new branch" or "Switched to and reset branch"
|
||||||
|
if !strings.Contains(out, "Switched to") {
|
||||||
return fmt.Errorf("unexpected branch creation output: %q", out)
|
return fmt.Errorf("unexpected branch creation output: %q", out)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ require (
|
|||||||
github.com/rakyll/statik v0.1.7
|
github.com/rakyll/statik v0.1.7
|
||||||
github.com/spf13/cobra v1.0.0
|
github.com/spf13/cobra v1.0.0
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
sigs.k8s.io/kustomize/api v0.8.10
|
sigs.k8s.io/kustomize/api v0.10.0
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0
|
sigs.k8s.io/kustomize/kyaml v0.12.0
|
||||||
)
|
)
|
||||||
|
|
||||||
replace sigs.k8s.io/kustomize/api => ../../api
|
|
||||||
|
|||||||
@@ -228,8 +228,10 @@ k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
|
|||||||
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.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA=
|
sigs.k8s.io/kustomize/api v0.10.0 h1:HK5gVSlVV24AmZ2fTHUIchZ6osaYNegK1jAdx7lJ/mU=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM=
|
sigs.k8s.io/kustomize/api v0.10.0/go.mod h1:syysqD8Oews9oghLfCitMCuCPxxu4MErSJ6uw8ge9jk=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.12.0 h1:k08l8SLwnKa/eXXB5GW2/OnEc/4gJF90VDFebsOwqw4=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.12.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E=
|
||||||
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=
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ chart repository.
|
|||||||
This example defines the `helm` command as
|
This example defines the `helm` command as
|
||||||
<!-- @defineHelmCommand @testHelm -->
|
<!-- @defineHelmCommand @testHelm -->
|
||||||
```
|
```
|
||||||
helmCommand=~/go/bin/helmV3
|
helmCommand=${MYGOBIN:-~/go/bin}/helmV3
|
||||||
```
|
```
|
||||||
|
|
||||||
This value is needed for testing this example in CI/CD.
|
This value is needed for testing this example in CI/CD.
|
||||||
|
|||||||
@@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# Unset CDPATH to restore default cd behavior. An exported CDPATH can
|
||||||
|
# cause cd to output the current directory to STDOUT.
|
||||||
|
unset CDPATH
|
||||||
|
|
||||||
where=$PWD
|
where=$PWD
|
||||||
|
|
||||||
release_url=https://api.github.com/repos/kubernetes-sigs/kustomize/releases
|
release_url=https://api.github.com/repos/kubernetes-sigs/kustomize/releases
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ fi
|
|||||||
# We test against the latest release, and HEAD, and presumably
|
# We test against the latest release, and HEAD, and presumably
|
||||||
# any branch using this label, so it should probably get
|
# any branch using this label, so it should probably get
|
||||||
# a new value.
|
# a new value.
|
||||||
|
export MYGOBIN
|
||||||
mdrip --mode test --blockTimeOut 15m \
|
mdrip --mode test --blockTimeOut 15m \
|
||||||
--label testAgainstLatestRelease examples
|
--label testAgainstLatestRelease examples
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ func NewCmdSet(fSys filesys.FileSystem, ldr ifc.KvLoader, v ifc.Validator) *cobr
|
|||||||
newCmdSetImage(fSys),
|
newCmdSetImage(fSys),
|
||||||
newCmdSetReplicas(fSys),
|
newCmdSetReplicas(fSys),
|
||||||
newCmdSetLabel(fSys, ldr.Validator().MakeLabelValidator()),
|
newCmdSetLabel(fSys, ldr.Validator().MakeLabelValidator()),
|
||||||
|
newCmdSetAnnotation(fSys, ldr.Validator().MakeAnnotationValidator()),
|
||||||
)
|
)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|||||||
99
kustomize/commands/edit/set/setannotation.go
Normal file
99
kustomize/commands/edit/set/setannotation.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package set
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kustomize/v4/commands/internal/kustfile"
|
||||||
|
"sigs.k8s.io/kustomize/kustomize/v4/commands/internal/util"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
|
)
|
||||||
|
|
||||||
|
type setAnnotationOptions struct {
|
||||||
|
metadata map[string]string
|
||||||
|
mapValidator func(map[string]string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidKey checks key against regex. First part for prefix segment (DNS1123Label) of an annotation followed by a slash, second part for name segment of an annotation
|
||||||
|
// see https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
|
||||||
|
var IsValidKey = regexp.MustCompile(`^([a-zA-Z](([-a-zA-Z0-9.]{0,251})[a-zA-Z0-9])?\/)?[a-zA-Z0-9]([-a-zA-Z0-9_.]{0,61}[a-zA-Z0-9])?$`).MatchString
|
||||||
|
|
||||||
|
// newCmdSetAnnotation sets one or more commonAnnotations to the kustomization file.
|
||||||
|
func newCmdSetAnnotation(fSys filesys.FileSystem, v func(map[string]string) error) *cobra.Command {
|
||||||
|
var o setAnnotationOptions
|
||||||
|
o.mapValidator = v
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "annotation",
|
||||||
|
Short: "Sets one or more commonAnnotations in " +
|
||||||
|
konfig.DefaultKustomizationFileName(),
|
||||||
|
Example: `
|
||||||
|
set annotation {annotationKey1:annotationValue1} {annotationKey2:annotationValue2}`,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return o.runE(args, fSys, o.setAnnotations)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *setAnnotationOptions) runE(
|
||||||
|
args []string, fSys filesys.FileSystem, setter func(*types.Kustomization) error) error {
|
||||||
|
err := o.validateAndParse(args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
kf, err := kustfile.NewKustomizationFile(fSys)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m, err := kf.Read()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = setter(m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return kf.Write(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateAndParse validates `set` commands and parses them into o.metadata
|
||||||
|
func (o *setAnnotationOptions) validateAndParse(args []string) error {
|
||||||
|
if len(args) < 1 {
|
||||||
|
return fmt.Errorf("must specify annotation")
|
||||||
|
}
|
||||||
|
m, err := util.ConvertSliceToMap(args, "annotation")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = o.mapValidator(m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for key := range m {
|
||||||
|
if !IsValidKey(key) {
|
||||||
|
return errors.New("invalid annotation key: see the syntax and character set rules at https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o.metadata = m
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *setAnnotationOptions) setAnnotations(m *types.Kustomization) error {
|
||||||
|
if m.CommonAnnotations == nil {
|
||||||
|
m.CommonAnnotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
return o.writeToMap(m.CommonAnnotations)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *setAnnotationOptions) writeToMap(m map[string]string) error {
|
||||||
|
for k, v := range o.metadata {
|
||||||
|
m[k] = v
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
229
kustomize/commands/edit/set/setannotation_test.go
Normal file
229
kustomize/commands/edit/set/setannotation_test.go
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package set
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
"sigs.k8s.io/kustomize/kustomize/v4/commands/internal/kustfile"
|
||||||
|
testutils_test "sigs.k8s.io/kustomize/kustomize/v4/commands/internal/testutils"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||||
|
)
|
||||||
|
|
||||||
|
const invalidAnnotationKey string = "invalid annotation key: see the syntax and character set rules at " +
|
||||||
|
"https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/"
|
||||||
|
|
||||||
|
func makeAnnotationKustomization(t *testing.T) *types.Kustomization {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
testutils_test.WriteTestKustomization(fSys)
|
||||||
|
kf, err := kustfile.NewKustomizationFile(fSys)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected new error %v", err)
|
||||||
|
}
|
||||||
|
m, err := kf.Read()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected read error %v", err)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunSetAnnotation(t *testing.T) {
|
||||||
|
var o setAnnotationOptions
|
||||||
|
o.metadata = map[string]string{"owls": "cute", "otters": "adorable"}
|
||||||
|
|
||||||
|
m := makeAnnotationKustomization(t)
|
||||||
|
err := o.setAnnotations(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: could not write to kustomization file")
|
||||||
|
}
|
||||||
|
// adding the same test input should work
|
||||||
|
err = o.setAnnotations(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: could not write to kustomization file")
|
||||||
|
}
|
||||||
|
// adding new annotations should work
|
||||||
|
o.metadata = map[string]string{"new": "annotation", "owls": "not cute"}
|
||||||
|
err = o.setAnnotations(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: could not write to kustomization file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotationNoArgs(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
v := valtest_test.MakeHappyMapValidator(t)
|
||||||
|
cmd := newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
err := cmd.Execute()
|
||||||
|
v.VerifyNoCall()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected an error")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if err.Error() != "must specify annotation" {
|
||||||
|
t.Errorf("incorrect error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotationInvalidFormat(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
v := valtest_test.MakeSadMapValidator(t)
|
||||||
|
cmd := newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
args := []string{"exclamation!:point"}
|
||||||
|
err := cmd.RunE(cmd, args)
|
||||||
|
v.VerifyCall()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected an error")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if err.Error() != valtest_test.SAD {
|
||||||
|
t.Errorf("incorrect error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotationPrefixColonName(t *testing.T) {
|
||||||
|
var o setAnnotationOptions
|
||||||
|
o.metadata = map[string]string{"internal.config.kubernetes.io/options": "true"}
|
||||||
|
|
||||||
|
m := makeAnnotationKustomization(t)
|
||||||
|
err := o.setAnnotations(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotation253Prefix63Name(t *testing.T) {
|
||||||
|
var o setAnnotationOptions
|
||||||
|
o.metadata = map[string]string{"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu" +
|
||||||
|
"vwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" +
|
||||||
|
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde" +
|
||||||
|
"fghijklmnopqrstuvwxyzabcdefghijklmnopqrs/abcdefghijklmnopqrstuvwxyzabcdefghijklmnop" +
|
||||||
|
"qrstuvwxyzabcdefghijk": "true"}
|
||||||
|
|
||||||
|
m := makeAnnotationKustomization(t)
|
||||||
|
err := o.setAnnotations(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotation254Prefix62Name(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
v := valtest_test.MakeHappyMapValidator(t)
|
||||||
|
cmd := newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
args := []string{"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi" +
|
||||||
|
"jklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn" +
|
||||||
|
"opqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs" +
|
||||||
|
"tuvwxyzabcdefghijklmnopqrst/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabc" +
|
||||||
|
"defghij:true"}
|
||||||
|
err := cmd.RunE(cmd, args)
|
||||||
|
v.VerifyCall()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected an error")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if err.Error() != invalidAnnotationKey {
|
||||||
|
t.Errorf("incorrect error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotation252Prefix64Name(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
v := valtest_test.MakeHappyMapValidator(t)
|
||||||
|
cmd := newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
args := []string{"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi" +
|
||||||
|
"jklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn" +
|
||||||
|
"opqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs" +
|
||||||
|
"tuvwxyzabcdefghijklmnopqr/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde" +
|
||||||
|
"fghijkl:true"}
|
||||||
|
err := cmd.RunE(cmd, args)
|
||||||
|
v.VerifyCall()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected an error")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if err.Error() != invalidAnnotationKey {
|
||||||
|
t.Errorf("incorrect error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotationNoKey(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
v := valtest_test.MakeHappyMapValidator(t)
|
||||||
|
cmd := newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
args := []string{":nokey"}
|
||||||
|
err := cmd.RunE(cmd, args)
|
||||||
|
v.VerifyNoCall()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected an error")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if err.Error() != "invalid annotation: ':nokey' (need k:v pair where v may be quoted)" {
|
||||||
|
t.Errorf("incorrect error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotationTooManyColons(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
testutils_test.WriteTestKustomization(fSys)
|
||||||
|
v := valtest_test.MakeHappyMapValidator(t)
|
||||||
|
cmd := newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
args := []string{"key:v1:v2"}
|
||||||
|
err := cmd.RunE(cmd, args)
|
||||||
|
v.VerifyCall()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotationNoValue(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
testutils_test.WriteTestKustomization(fSys)
|
||||||
|
v := valtest_test.MakeHappyMapValidator(t)
|
||||||
|
cmd := newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
args := []string{"no,value:"}
|
||||||
|
err := cmd.RunE(cmd, args)
|
||||||
|
v.VerifyCall()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected an error")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if err.Error() != invalidAnnotationKey {
|
||||||
|
t.Errorf("incorrect error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotationMultipleArgs(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
testutils_test.WriteTestKustomization(fSys)
|
||||||
|
v := valtest_test.MakeHappyMapValidator(t)
|
||||||
|
cmd := newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
args := []string{"this:input", "has:spaces"}
|
||||||
|
err := cmd.RunE(cmd, args)
|
||||||
|
v.VerifyCall()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAnnotationExisting(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
testutils_test.WriteTestKustomization(fSys)
|
||||||
|
v := valtest_test.MakeHappyMapValidator(t)
|
||||||
|
cmd := newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
args := []string{"key:foo"}
|
||||||
|
err := cmd.RunE(cmd, args)
|
||||||
|
v.VerifyCall()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err.Error())
|
||||||
|
}
|
||||||
|
v = valtest_test.MakeHappyMapValidator(t)
|
||||||
|
cmd = newCmdSetAnnotation(fSys, v.Validator)
|
||||||
|
err = cmd.RunE(cmd, args)
|
||||||
|
v.VerifyCall()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -212,7 +212,7 @@ func (mf *kustomizationFile) parseCommentedFields(content []byte) error {
|
|||||||
if matched {
|
if matched {
|
||||||
mf.originalFields = append(mf.originalFields, &commentedField{field: field, comment: squash(comments)})
|
mf.originalFields = append(mf.originalFields, &commentedField{field: field, comment: squash(comments)})
|
||||||
comments = [][]byte{}
|
comments = [][]byte{}
|
||||||
} else if len(comments) > 0 {
|
} else if len(comments) > 0 && len(mf.originalFields) > 0 {
|
||||||
mf.originalFields[len(mf.originalFields)-1].appendComment(squash(comments))
|
mf.originalFields[len(mf.originalFields)-1].appendComment(squash(comments))
|
||||||
comments = [][]byte{}
|
comments = [][]byte{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -356,6 +356,53 @@ kind: Kustomization
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommentsWithDocumentSeperatorAtBeginning(t *testing.T) {
|
||||||
|
kustomizationContentWithComments := []byte(`
|
||||||
|
|
||||||
|
|
||||||
|
# Some comments
|
||||||
|
# This is some comment we should preserve
|
||||||
|
# don't delete it
|
||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: mynamespace
|
||||||
|
`)
|
||||||
|
|
||||||
|
expected := []byte(`
|
||||||
|
|
||||||
|
|
||||||
|
# Some comments
|
||||||
|
# This is some comment we should preserve
|
||||||
|
# don't delete it
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: mynamespace
|
||||||
|
`)
|
||||||
|
fSys := filesys.MakeFsInMemory()
|
||||||
|
testutils_test.WriteTestKustomizationWith(
|
||||||
|
fSys, kustomizationContentWithComments)
|
||||||
|
mf, err := NewKustomizationFile(fSys)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected Error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
kustomization, err := mf.Read()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected Error: %v", err)
|
||||||
|
}
|
||||||
|
if err = mf.Write(kustomization); err != nil {
|
||||||
|
t.Fatalf("Unexpected Error: %v", err)
|
||||||
|
}
|
||||||
|
bytes, _ := fSys.ReadFile(mf.path)
|
||||||
|
|
||||||
|
if diff := cmp.Diff(expected, bytes); diff != "" {
|
||||||
|
t.Errorf("Mismatch (-expected, +actual):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnknownFieldInKustomization(t *testing.T) {
|
func TestUnknownFieldInKustomization(t *testing.T) {
|
||||||
kContent := []byte(`
|
kContent := []byte(`
|
||||||
foo:
|
foo:
|
||||||
|
|||||||
@@ -8,26 +8,38 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var format string
|
||||||
|
|
||||||
// NewCmdFetch makes a new fetch command.
|
// NewCmdFetch makes a new fetch command.
|
||||||
func NewCmdFetch(w io.Writer) *cobra.Command {
|
func NewCmdFetch(w io.Writer) *cobra.Command {
|
||||||
infoCmd := cobra.Command{
|
fetchCmd := cobra.Command{
|
||||||
Use: "fetch",
|
Use: "fetch",
|
||||||
Short: `Fetches the OpenAPI specification from the current kubernetes cluster specified
|
Short: `Fetches the OpenAPI specification from the current kubernetes cluster specified
|
||||||
in the user's kubeconfig`,
|
in the user's kubeconfig`,
|
||||||
Example: `kustomize openapi fetch`,
|
Example: `kustomize openapi fetch`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
printSchema(w)
|
return printSchema(w)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return &infoCmd
|
fetchCmd.Flags().StringVar(
|
||||||
|
&format,
|
||||||
|
"format",
|
||||||
|
"json",
|
||||||
|
"Specify format for fetched schema ('json' or 'yaml')")
|
||||||
|
return &fetchCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func printSchema(w io.Writer) {
|
func printSchema(w io.Writer) error {
|
||||||
|
if format != "json" && format != "yaml" {
|
||||||
|
return fmt.Errorf("format must be either 'json' or 'yaml'")
|
||||||
|
}
|
||||||
|
|
||||||
errMsg := `
|
errMsg := `
|
||||||
Error fetching schema from cluster.
|
Error fetching schema from cluster.
|
||||||
Please make sure kubectl is installed and its context is set correctly.
|
Please make sure kubectl is installed, its context is set correctly, and your cluster is up.
|
||||||
Installation and setup instructions: https://kubernetes.io/docs/tasks/tools/install-kubectl/`
|
Installation and setup instructions: https://kubernetes.io/docs/tasks/tools/install-kubectl/`
|
||||||
|
|
||||||
command := exec.Command("kubectl", []string{"get", "--raw", "/openapi/v2"}...)
|
command := exec.Command("kubectl", []string{"get", "--raw", "/openapi/v2"}...)
|
||||||
@@ -36,9 +48,10 @@ Installation and setup instructions: https://kubernetes.io/docs/tasks/tools/inst
|
|||||||
command.Stdout = &stdout
|
command.Stdout = &stdout
|
||||||
command.Stderr = &stderr
|
command.Stderr = &stderr
|
||||||
err := command.Run()
|
err := command.Run()
|
||||||
if err != nil || stdout.String() == "" {
|
if err != nil {
|
||||||
fmt.Fprintln(w, err, stderr.String()+errMsg)
|
return fmt.Errorf("%w\n%s", err, stderr.String()+errMsg)
|
||||||
return
|
} else if stdout.String() == "" {
|
||||||
|
return fmt.Errorf(stderr.String() + errMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// format and output
|
// format and output
|
||||||
@@ -46,5 +59,14 @@ Installation and setup instructions: https://kubernetes.io/docs/tasks/tools/inst
|
|||||||
output := stdout.Bytes()
|
output := stdout.Bytes()
|
||||||
json.Unmarshal(output, &jsonSchema)
|
json.Unmarshal(output, &jsonSchema)
|
||||||
output, _ = json.MarshalIndent(jsonSchema, "", " ")
|
output, _ = json.MarshalIndent(jsonSchema, "", " ")
|
||||||
|
|
||||||
|
if format == "yaml" {
|
||||||
|
output, err = yaml.JSONToYAML(output)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Fprintln(w, string(output))
|
fmt.Fprintln(w, string(output))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ require (
|
|||||||
github.com/spf13/cobra v1.0.0
|
github.com/spf13/cobra v1.0.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
sigs.k8s.io/kustomize/api v0.8.10
|
sigs.k8s.io/kustomize/api v0.10.0
|
||||||
sigs.k8s.io/kustomize/cmd/config v0.9.13
|
sigs.k8s.io/kustomize/cmd/config v0.10.1
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0
|
sigs.k8s.io/kustomize/kyaml v0.12.0
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,5 +18,3 @@ exclude (
|
|||||||
sigs.k8s.io/kustomize/api v0.2.0
|
sigs.k8s.io/kustomize/api v0.2.0
|
||||||
sigs.k8s.io/kustomize/cmd/config v0.2.0
|
sigs.k8s.io/kustomize/cmd/config v0.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
replace sigs.k8s.io/kustomize/api => ../api
|
|
||||||
|
|||||||
@@ -253,10 +253,12 @@ k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
|
|||||||
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/cmd/config v0.9.13 h1:lqOf0QcFhNvgZkgrPINNRs7TxEO7IGVtLMyUJId3oRE=
|
sigs.k8s.io/kustomize/api v0.10.0 h1:HK5gVSlVV24AmZ2fTHUIchZ6osaYNegK1jAdx7lJ/mU=
|
||||||
sigs.k8s.io/kustomize/cmd/config v0.9.13/go.mod h1:7547FLF8W/lTaDf0BDqFTbZxM9zqwEJqCKN9sSR0xSs=
|
sigs.k8s.io/kustomize/api v0.10.0/go.mod h1:syysqD8Oews9oghLfCitMCuCPxxu4MErSJ6uw8ge9jk=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA=
|
sigs.k8s.io/kustomize/cmd/config v0.10.1 h1:eqpN9eUSn3XIfvPabit8lpIqUbWKS7f4lOB4D2cr5CQ=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM=
|
sigs.k8s.io/kustomize/cmd/config v0.10.1/go.mod h1:9W5pDv3cgDfMjOXEga4yC9lUpkgAaecW+lZmHOMeX2I=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.12.0 h1:k08l8SLwnKa/eXXB5GW2/OnEc/4gJF90VDFebsOwqw4=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.12.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E=
|
||||||
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=
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user