mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-14 10:30:59 +00:00
Compare commits
500 Commits
no-partial
...
release-ap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42873c8d2a | ||
|
|
277da9ed21 | ||
|
|
2b00d887fd | ||
|
|
08d0593c3e | ||
|
|
31706fd7fd | ||
|
|
e862612703 | ||
|
|
1b449768b5 | ||
|
|
a9f7a0427a | ||
|
|
cd954ce6fe | ||
|
|
10c292f501 | ||
|
|
a9bfabc771 | ||
|
|
398aa3666f | ||
|
|
8f2d2436ec | ||
|
|
fd06780f3e | ||
|
|
562cbc132d | ||
|
|
d5f3c4fad9 | ||
|
|
f1599f6498 | ||
|
|
c0b3801c7a | ||
|
|
f0681429ea | ||
|
|
a6bbbe843c | ||
|
|
2c68a4d2d4 | ||
|
|
b3d1df2644 | ||
|
|
8d21d43cf7 | ||
|
|
eabf2d41d3 | ||
|
|
ed2ca23400 | ||
|
|
6145a4be44 | ||
|
|
8fef99fa35 | ||
|
|
a6149b1c88 | ||
|
|
91b92b52c1 | ||
|
|
d7e60b8451 | ||
|
|
9db92fd28d | ||
|
|
d514df3db0 | ||
|
|
22ce9c02bf | ||
|
|
43868688d5 | ||
|
|
434a55a244 | ||
|
|
a6ea3e2bb6 | ||
|
|
72f0a3cfb1 | ||
|
|
1eccd8f4b7 | ||
|
|
4dbc0d22e1 | ||
|
|
e9fc57abd6 | ||
|
|
d35edbf80d | ||
|
|
da3985c284 | ||
|
|
14a9a9849f | ||
|
|
8aafbacd17 | ||
|
|
4da880d6cb | ||
|
|
62eca858f3 | ||
|
|
11704312be | ||
|
|
74ba2fb141 | ||
|
|
cc410bc23a | ||
|
|
2252fd951a | ||
|
|
33caee50cb | ||
|
|
28ef9da0d9 | ||
|
|
db2240c9c1 | ||
|
|
d3329453a2 | ||
|
|
6ffcc08591 | ||
|
|
facabded61 | ||
|
|
9d66eb16c8 | ||
|
|
6088692165 | ||
|
|
9e68399e04 | ||
|
|
e25f99ee02 | ||
|
|
37715863f0 | ||
|
|
3e69c2e36a | ||
|
|
17eab513e9 | ||
|
|
800e12b5ae | ||
|
|
96c6bbad2c | ||
|
|
1fa02e729d | ||
|
|
f93b0ead3c | ||
|
|
f80650e8ce | ||
|
|
bcf100f592 | ||
|
|
9546529f1d | ||
|
|
91ccf00ac8 | ||
|
|
f8f4203fb7 | ||
|
|
537c4fa5c2 | ||
|
|
dc7ebef925 | ||
|
|
b154361c00 | ||
|
|
3bb9a6d414 | ||
|
|
14c091aec7 | ||
|
|
6c1fea79ed | ||
|
|
ca8d629230 | ||
|
|
fd09a6ed50 | ||
|
|
23fbdd2ab5 | ||
|
|
27a8ff9d23 | ||
|
|
cf01ceb2f6 | ||
|
|
3bd9ea8ee7 | ||
|
|
d223b9d55e | ||
|
|
31b852c7bc | ||
|
|
add367bf2e | ||
|
|
b1b61ad4cf | ||
|
|
d73f0fd097 | ||
|
|
bf286dce76 | ||
|
|
d768fc371c | ||
|
|
7e392f9117 | ||
|
|
4675bec08a | ||
|
|
26165a86b7 | ||
|
|
69826668a7 | ||
|
|
a85dfd4141 | ||
|
|
abdcae870c | ||
|
|
dd49bd4c6d | ||
|
|
4adb7f9604 | ||
|
|
40ce15cca3 | ||
|
|
4e93959754 | ||
|
|
ab519fdc13 | ||
|
|
f3fedac429 | ||
|
|
872968c420 | ||
|
|
f72db33d5e | ||
|
|
cfa2c41b44 | ||
|
|
0c461d61df | ||
|
|
27ae0693b4 | ||
|
|
42d5870546 | ||
|
|
f814039f99 | ||
|
|
b28e0445a2 | ||
|
|
7db7de65c1 | ||
|
|
a34dd1fc3f | ||
|
|
cd886102a9 | ||
|
|
2831689a1b | ||
|
|
069c5fd5d7 | ||
|
|
504e805da0 | ||
|
|
3cf12635d4 | ||
|
|
9adb7535fa | ||
|
|
c87c7a139c | ||
|
|
50583c4b0e | ||
|
|
9a7014cc14 | ||
|
|
32a78f3915 | ||
|
|
f866701088 | ||
|
|
49e911fcef | ||
|
|
665bfbc32d | ||
|
|
a0a9bdfe05 | ||
|
|
16f7e42392 | ||
|
|
bf485f66d3 | ||
|
|
557d6cba2d | ||
|
|
8eee90d2c6 | ||
|
|
9da0cf8b4c | ||
|
|
c259c478e5 | ||
|
|
c2ec4bb482 | ||
|
|
29d0214cbd | ||
|
|
faf93bb71d | ||
|
|
71f6f4c7d7 | ||
|
|
b22dbc7db9 | ||
|
|
bfe18b8198 | ||
|
|
82bd395289 | ||
|
|
e3031f3a7b | ||
|
|
6f47203e3f | ||
|
|
afc2357d5f | ||
|
|
c1ae80d25d | ||
|
|
f23d45fcb4 | ||
|
|
0b4974eb1c | ||
|
|
228d22cff0 | ||
|
|
bfb00ecb27 | ||
|
|
fefa21fa01 | ||
|
|
bb7003e557 | ||
|
|
0122aa82ef | ||
|
|
7db6c203d5 | ||
|
|
42394090df | ||
|
|
447d433457 | ||
|
|
9b54286933 | ||
|
|
d2549312d6 | ||
|
|
fdf8f44c90 | ||
|
|
30893b0184 | ||
|
|
eb7f91ffcd | ||
|
|
413e01e52c | ||
|
|
b57b3abc49 | ||
|
|
4ae9f53593 | ||
|
|
265195ca80 | ||
|
|
8b52e04c3a | ||
|
|
572a096e60 | ||
|
|
4d7b8efc3e | ||
|
|
fa32631993 | ||
|
|
ec3be81217 | ||
|
|
53c86258a6 | ||
|
|
7226ba5086 | ||
|
|
e219b8864e | ||
|
|
863ca93f0b | ||
|
|
68e0997dc9 | ||
|
|
dc29923a08 | ||
|
|
f7bc0aced8 | ||
|
|
e7c8ed1899 | ||
|
|
b8443683f9 | ||
|
|
2fda12d220 | ||
|
|
790ca0e7b6 | ||
|
|
d5dd5f4567 | ||
|
|
5b51722720 | ||
|
|
6640f8799e | ||
|
|
790dbf0fdf | ||
|
|
b7b85b10fc | ||
|
|
5505af439a | ||
|
|
cc35d3c4e5 | ||
|
|
a0f131cf86 | ||
|
|
f87942ec76 | ||
|
|
af7c088053 | ||
|
|
7af4e772bd | ||
|
|
67a0b43c81 | ||
|
|
2bff0d6882 | ||
|
|
2ab117166f | ||
|
|
8effd35d3f | ||
|
|
b1f100e3da | ||
|
|
e002b49244 | ||
|
|
bd435d4154 | ||
|
|
a869386996 | ||
|
|
a40379782e | ||
|
|
761893d1fc | ||
|
|
9f4f9b323c | ||
|
|
48fd585620 | ||
|
|
96ad106ee1 | ||
|
|
e2b0297d18 | ||
|
|
d6fa69d26e | ||
|
|
cba3f1115f | ||
|
|
5568521cd1 | ||
|
|
a5a2db577f | ||
|
|
b6387b9eaf | ||
|
|
0f2618b21d | ||
|
|
0465637335 | ||
|
|
e71072b90b | ||
|
|
289e78c136 | ||
|
|
001ab61b37 | ||
|
|
16395012d1 | ||
|
|
5497967665 | ||
|
|
0115ae6da4 | ||
|
|
bb5022441a | ||
|
|
8668b74622 | ||
|
|
752bb2ef41 | ||
|
|
bde28b1320 | ||
|
|
689dcefa3a | ||
|
|
f3e263a051 | ||
|
|
fa48ab16bf | ||
|
|
0eca5c4b06 | ||
|
|
6b76c807f5 | ||
|
|
76695414c7 | ||
|
|
d64ac13447 | ||
|
|
50159d47c2 | ||
|
|
f80d9c41e5 | ||
|
|
2f99707792 | ||
|
|
7a08dde7ac | ||
|
|
81297df4ff | ||
|
|
c4137c0c2a | ||
|
|
944c72a275 | ||
|
|
46e2d72213 | ||
|
|
6cb85e8544 | ||
|
|
6ef9773c02 | ||
|
|
11aa57e67f | ||
|
|
779f153071 | ||
|
|
60d7ee6710 | ||
|
|
852739c477 | ||
|
|
bee2e5f50c | ||
|
|
ace2d53b18 | ||
|
|
f910219c7a | ||
|
|
aeb7cb2a40 | ||
|
|
a7e065ddb4 | ||
|
|
713842330e | ||
|
|
5936a892a7 | ||
|
|
c3a4f3eab6 | ||
|
|
fb7ee2f487 | ||
|
|
45e57f0228 | ||
|
|
d20a7c4996 | ||
|
|
9920586b22 | ||
|
|
61dad14345 | ||
|
|
f65506d285 | ||
|
|
cbbd1599f2 | ||
|
|
4b34ff3075 | ||
|
|
654d7953d9 | ||
|
|
d91ea65f5a | ||
|
|
7911b2c001 | ||
|
|
0d854a5144 | ||
|
|
cb5b241715 | ||
|
|
039b05fb16 | ||
|
|
9c1d412dac | ||
|
|
a318d4db26 | ||
|
|
0cfafddacc | ||
|
|
f5ca753377 | ||
|
|
0d4849ff98 | ||
|
|
e3b9afcfaa | ||
|
|
af781bfa5e | ||
|
|
7dd9637b1a | ||
|
|
ddce57b585 | ||
|
|
11fc419cee | ||
|
|
a8dec66a84 | ||
|
|
7e541ca380 | ||
|
|
1bd58bdc15 | ||
|
|
9107fa3c81 | ||
|
|
df0cd3c4a3 | ||
|
|
f3b34c44b5 | ||
|
|
9e101ee97f | ||
|
|
433be59ea7 | ||
|
|
2c444d6bf4 | ||
|
|
a90c19d577 | ||
|
|
8f283499e9 | ||
|
|
d78fe665a7 | ||
|
|
532abf77e7 | ||
|
|
59696d1ace | ||
|
|
d30e457031 | ||
|
|
ae041b5c54 | ||
|
|
a2b60e4bcb | ||
|
|
9d126f6dd8 | ||
|
|
bd8045b648 | ||
|
|
5c1a022a3c | ||
|
|
e19ca5405a | ||
|
|
56d37acc7d | ||
|
|
0571a2f15d | ||
|
|
0cdfa5b3dc | ||
|
|
7b9880aaab | ||
|
|
7c36ed21b3 | ||
|
|
985835f96f | ||
|
|
f81765b96e | ||
|
|
a2ceaff053 | ||
|
|
94181b1be7 | ||
|
|
9966387002 | ||
|
|
169fdd7330 | ||
|
|
78b8139d46 | ||
|
|
76f8d2828b | ||
|
|
b692e49b1e | ||
|
|
bd7f001c26 | ||
|
|
d6ff768298 | ||
|
|
4947a905fa | ||
|
|
cd9a16cfab | ||
|
|
02a53f193d | ||
|
|
b1717c8a97 | ||
|
|
911ddcda40 | ||
|
|
daf06622a2 | ||
|
|
9f1d5acdc8 | ||
|
|
9756d92a91 | ||
|
|
d32d1937e6 | ||
|
|
ddcbae54ab | ||
|
|
ca748faa3f | ||
|
|
5e6cbac589 | ||
|
|
ff75dd6cd5 | ||
|
|
f8391994b4 | ||
|
|
5ce14e5024 | ||
|
|
ee22c9cab7 | ||
|
|
4a893ce8c6 | ||
|
|
9ce923ebeb | ||
|
|
494a807f28 | ||
|
|
820f17c73b | ||
|
|
cd7ba1744e | ||
|
|
da4e881007 | ||
|
|
878cda7c55 | ||
|
|
47327616df | ||
|
|
eeff67d88d | ||
|
|
6adf4f294a | ||
|
|
5e7cc3437d | ||
|
|
ded76df3af | ||
|
|
d7362ed22d | ||
|
|
4711bfe40c | ||
|
|
8c0e0b3b47 | ||
|
|
096b2c4435 | ||
|
|
129d0f90af | ||
|
|
c76fd5eb85 | ||
|
|
9e42f8d57e | ||
|
|
168e31bfb6 | ||
|
|
d37c0eb477 | ||
|
|
691b7d1df3 | ||
|
|
336bc14e1a | ||
|
|
b2c39b61bb | ||
|
|
da31b966fb | ||
|
|
dce94267fb | ||
|
|
d1647a51af | ||
|
|
5b76aa9d2f | ||
|
|
0add0f95e2 | ||
|
|
6ce0bf390c | ||
|
|
7c98e531f2 | ||
|
|
e1ab8c79c1 | ||
|
|
cf3e81b590 | ||
|
|
565cff2d07 | ||
|
|
8383b28322 | ||
|
|
e1c530e420 | ||
|
|
035924bc1e | ||
|
|
fd508f0e3a | ||
|
|
9407e26433 | ||
|
|
3cac8448d3 | ||
|
|
84642b1fed | ||
|
|
fa574866b4 | ||
|
|
4b807107a6 | ||
|
|
6bb62dd6ef | ||
|
|
3d6f40bd5e | ||
|
|
c2bd42e774 | ||
|
|
529a25d30b | ||
|
|
ccdc148472 | ||
|
|
7dcb2a50ff | ||
|
|
1e3215226e | ||
|
|
459d0198d9 | ||
|
|
3abf91644e | ||
|
|
1f98338481 | ||
|
|
91078545e6 | ||
|
|
467633c2de | ||
|
|
e44df7b386 | ||
|
|
bbff6768da | ||
|
|
0020a496f7 | ||
|
|
5a3e920902 | ||
|
|
96f893f350 | ||
|
|
97c8cd7d1a | ||
|
|
ee3f506d10 | ||
|
|
0f244a4a07 | ||
|
|
c79916b1ba | ||
|
|
2ce1c7cce3 | ||
|
|
75fa235498 | ||
|
|
7413c6a5fb | ||
|
|
315ed56450 | ||
|
|
9eddc3c5a7 | ||
|
|
38d5bf8e09 | ||
|
|
85d623bc86 | ||
|
|
928b823d8f | ||
|
|
2c2b2ab825 | ||
|
|
d3184da4c6 | ||
|
|
eadb469712 | ||
|
|
2649d39fd3 | ||
|
|
faab836ec9 | ||
|
|
c9f500cc0b | ||
|
|
42bf3c0e2b | ||
|
|
3b395a9da2 | ||
|
|
633da991d2 | ||
|
|
e07b8a5d15 | ||
|
|
71a7a7df13 | ||
|
|
436a047617 | ||
|
|
4d70a36c25 | ||
|
|
304d0e951f | ||
|
|
2fdb35614d | ||
|
|
5dff9df1f7 | ||
|
|
84682a1159 | ||
|
|
c151147258 | ||
|
|
317fcadccb | ||
|
|
a2e9682002 | ||
|
|
5dcf0ae683 | ||
|
|
ce3e394a41 | ||
|
|
0c92647760 | ||
|
|
39527da73c | ||
|
|
fa90046136 | ||
|
|
efe1374940 | ||
|
|
b751ffe5a0 | ||
|
|
28a2a01c29 | ||
|
|
0c650423ed | ||
|
|
4ffc861854 | ||
|
|
8338873e56 | ||
|
|
dd520f8889 | ||
|
|
4842d8be60 | ||
|
|
bf6e6ad33b | ||
|
|
e1094da3cf | ||
|
|
7d150ce973 | ||
|
|
39264a7057 | ||
|
|
736e166168 | ||
|
|
e8b521e3ab | ||
|
|
694b3c9318 | ||
|
|
a4954d386a | ||
|
|
976193ce70 | ||
|
|
ee0b26601b | ||
|
|
78e310231e | ||
|
|
ffa554b371 | ||
|
|
68a0fc95da | ||
|
|
9b43e76947 | ||
|
|
adf760e246 | ||
|
|
7a89df8350 | ||
|
|
93d7511b38 | ||
|
|
7c33fe30b7 | ||
|
|
cd49194383 | ||
|
|
22dbd3eb17 | ||
|
|
53a4134379 | ||
|
|
51e2714408 | ||
|
|
d825beff27 | ||
|
|
aa4eb59bb0 | ||
|
|
00d450cce7 | ||
|
|
a090ceac6c | ||
|
|
63c37b1780 | ||
|
|
dfd2d7600d | ||
|
|
0fd385d719 | ||
|
|
57d8583887 | ||
|
|
9c116e9031 | ||
|
|
e6c16a6ddc | ||
|
|
03669a1804 | ||
|
|
3c44db8746 | ||
|
|
9a1a203b52 | ||
|
|
8b51c295a1 | ||
|
|
738ca56ccd | ||
|
|
f901b4a5fd | ||
|
|
4fff8399ea | ||
|
|
e532d6f1a1 | ||
|
|
db2a3800ed | ||
|
|
183928e6ba | ||
|
|
c0e2030905 | ||
|
|
87c428e7cd | ||
|
|
f5ad795995 | ||
|
|
f851cc7181 | ||
|
|
7e3ad53890 | ||
|
|
5cdc080406 | ||
|
|
10fb04cdf2 | ||
|
|
ea8fc77f2f | ||
|
|
e9507c940d | ||
|
|
bea105d793 | ||
|
|
e4d7eaa479 | ||
|
|
85949329b8 | ||
|
|
0c34cf4192 | ||
|
|
95edcc0681 | ||
|
|
9d8ed39d3d | ||
|
|
1957d5c746 | ||
|
|
236166097e | ||
|
|
3370177b9d | ||
|
|
c8b112c79f | ||
|
|
d91e31cf18 | ||
|
|
00b0bd8473 | ||
|
|
e2aff13587 | ||
|
|
361154dabc | ||
|
|
7db330d2cc | ||
|
|
ffd45f6893 | ||
|
|
7aa33ff471 |
@@ -1,7 +1,5 @@
|
||||
.github
|
||||
docs
|
||||
examples
|
||||
hack
|
||||
site
|
||||
travis
|
||||
*.md
|
||||
|
||||
8
.github/dependabot.yml
vendored
8
.github/dependabot.yml
vendored
@@ -4,3 +4,11 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: gomod
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
vulnerability-alerts:
|
||||
enabled: true
|
||||
36
.github/workflows/apidiff.yml
vendored
Normal file
36
.github/workflows/apidiff.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: APIDiff
|
||||
|
||||
# Trigger the workflow on pull requests and direct pushes to any branch
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
go-apidiff:
|
||||
name: Verify API differences
|
||||
runs-on: ubuntu-latest
|
||||
# Pull requests from different repository only trigger this checks
|
||||
if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: Clone the code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.work
|
||||
- name: Execute go-apidiff
|
||||
uses: joelanford/go-apidiff@v0.8.2
|
||||
with:
|
||||
compare-imports: true
|
||||
print-compatible: true
|
||||
- name: Report failure
|
||||
uses: nashmaniac/create-issue-action@v1.2
|
||||
# Only report failures of pushes (PRs have are visible through the Checks section) to the default branch
|
||||
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
with:
|
||||
title: 🐛 go-apidiff failed for ${{ github.sha }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: kind/bug
|
||||
body: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
132
.github/workflows/go.yml
vendored
132
.github/workflows/go.yml
vendored
@@ -10,93 +10,101 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
conditional-changes:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: read
|
||||
outputs:
|
||||
doc: ${{ steps.filter.outputs.doc }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
doc:
|
||||
- 'site/**'
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
needs: conditional-changes
|
||||
if: needs.conditional-changes.outputs.doc == 'false'
|
||||
runs-on: [ubuntu-latest]
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.19.0'
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.work
|
||||
id: go
|
||||
- name: Lint
|
||||
run: make lint
|
||||
|
||||
- name: Verify boilerplate
|
||||
run: make check-license
|
||||
|
||||
test-linux:
|
||||
name: Test Linux
|
||||
needs: conditional-changes
|
||||
if: needs.conditional-changes.outputs.doc == 'false'
|
||||
runs-on: [ubuntu-latest]
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.19.0'
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Test all modules
|
||||
run: make test-unit-non-plugin
|
||||
env:
|
||||
KUSTOMIZE_DOCKER_E2E: true
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.work
|
||||
id: go
|
||||
- name: Test all modules
|
||||
run: make test-unit-non-plugin
|
||||
env:
|
||||
KUSTOMIZE_DOCKER_E2E: true
|
||||
|
||||
test-macos:
|
||||
name: Test MacOS
|
||||
needs: conditional-changes
|
||||
if: needs.conditional-changes.outputs.doc == 'false'
|
||||
runs-on: [macos-latest]
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.19.0'
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Test all modules
|
||||
run: make test-unit-non-plugin
|
||||
env:
|
||||
KUSTOMIZE_DOCKER_E2E: false # docker not installed on mac
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.work
|
||||
id: go
|
||||
- name: Test all modules
|
||||
run: make test-unit-non-plugin
|
||||
env:
|
||||
KUSTOMIZE_DOCKER_E2E: false # docker not installed on mac
|
||||
|
||||
test-windows:
|
||||
name: Test Windows
|
||||
needs: conditional-changes
|
||||
if: needs.conditional-changes.outputs.doc == 'false'
|
||||
runs-on: [windows-latest]
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.work
|
||||
id: go
|
||||
- name: Test kyaml
|
||||
run: go test -cover ./...
|
||||
working-directory: ./kyaml
|
||||
- name: Test cmd/config
|
||||
run: go test -cover ./...
|
||||
working-directory: ./cmd/config
|
||||
env:
|
||||
KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet
|
||||
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.19.0'
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Test kyaml
|
||||
run: go test -cover ./...
|
||||
working-directory: ./kyaml
|
||||
|
||||
- name: Test cmd/config
|
||||
run: go test -cover ./...
|
||||
working-directory: ./cmd/config
|
||||
env:
|
||||
KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet
|
||||
|
||||
# TODO (#4001): replace specific modules above with this once Windows tests are passing.
|
||||
#- name: Test all modules
|
||||
# run: make test-unit-non-plugin
|
||||
# env:
|
||||
# KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet
|
||||
# TODO (#4001): replace specific modules above with this once Windows tests are passing.
|
||||
#- name: Test all modules
|
||||
# run: make test-unit-non-plugin
|
||||
# env:
|
||||
# KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet
|
||||
|
||||
27
.github/workflows/release.yaml
vendored
Normal file
27
.github/workflows/release.yaml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- kyaml/v*
|
||||
- cmd/config/v*
|
||||
- api/v*
|
||||
- kustomize/v*
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.work
|
||||
id: go
|
||||
- run: ./releasing/create-release.sh "${tag}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: ${{ github.ref_name }}
|
||||
123
.golangci.yml
123
.golangci.yml
@@ -3,96 +3,42 @@
|
||||
|
||||
run:
|
||||
deadline: 5m
|
||||
go: '1.19'
|
||||
go: '1.21'
|
||||
|
||||
linters:
|
||||
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||
disable-all: true
|
||||
enable:
|
||||
- asciicheck
|
||||
- bidichk
|
||||
- bodyclose
|
||||
- contextcheck
|
||||
# - cyclop
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupl
|
||||
- dupword
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errname
|
||||
- errorlint
|
||||
- exhaustive
|
||||
# - exhaustivestruct
|
||||
- exportloopref
|
||||
# - forbidigo
|
||||
- forcetypeassert
|
||||
# - funlen
|
||||
# - gci
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
# - gocognit
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
# - godot
|
||||
# - godox
|
||||
# - goerr113
|
||||
- gofmt
|
||||
# - gofumpt
|
||||
- goheader
|
||||
- goimports
|
||||
- gomnd
|
||||
- gomoddirectives
|
||||
- gomodguard
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
# - ifshort # too many false positives
|
||||
- importas
|
||||
- ineffassign
|
||||
# - ireturn
|
||||
- lll
|
||||
- makezero
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- nilerr
|
||||
# - nilnil
|
||||
# - nlreturn
|
||||
# - noctx
|
||||
- nolintlint
|
||||
# - paralleltest
|
||||
- prealloc
|
||||
- predeclared
|
||||
- promlinter
|
||||
- revive
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
# - stylecheck
|
||||
- tagliatelle
|
||||
- tenv
|
||||
- testpackage
|
||||
- testableexamples
|
||||
- thelper
|
||||
- tparallel
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
# - varnamelen
|
||||
- wastedassign
|
||||
- whitespace
|
||||
- wrapcheck
|
||||
# - wsl
|
||||
- asasalint
|
||||
- usestdlibvars
|
||||
- interfacebloat
|
||||
- loggercheck
|
||||
- reassign
|
||||
enable-all: true
|
||||
disable:
|
||||
- cyclop
|
||||
- exhaustivestruct
|
||||
- forbidigo
|
||||
- funlen
|
||||
- gci
|
||||
- gocognit
|
||||
- godot
|
||||
- godox
|
||||
- goerr113
|
||||
- gofumpt
|
||||
- ifshort # too many false positives
|
||||
- ireturn
|
||||
- nilnil
|
||||
- nlreturn
|
||||
- noctx
|
||||
- paralleltest
|
||||
- stylecheck
|
||||
- varnamelen
|
||||
- wsl
|
||||
- exhaustruct
|
||||
- deadcode
|
||||
- scopelint
|
||||
- nonamedreturns
|
||||
- golint
|
||||
- maintidx
|
||||
- nosnakecase
|
||||
- testpackage # it's better to keep tests in the same package for now because kustomize does open box testing
|
||||
- structcheck # abandoned by author
|
||||
- varcheck # abandoned by author
|
||||
- maligned # abandoned by author
|
||||
- interfacer # archived by author
|
||||
|
||||
linters-settings:
|
||||
dupl:
|
||||
@@ -110,6 +56,7 @@ linters-settings:
|
||||
gomnd:
|
||||
ignored-functions:
|
||||
- os.WriteFile
|
||||
- make
|
||||
gomoddirectives:
|
||||
replace-local: true
|
||||
gosec:
|
||||
|
||||
222
CONTRIBUTING.md
222
CONTRIBUTING.md
@@ -13,6 +13,7 @@
|
||||
[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
|
||||
|
||||
[Kustomize Architecture]: ARCHITECTURE.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/
|
||||
@@ -25,13 +26,88 @@ _As contributors and maintainers of this project, and in the interest of fosteri
|
||||
|
||||
## Getting Started
|
||||
|
||||
Dev guides:
|
||||
### Forking Kustomize and Working Locally
|
||||
The Kustomize project uses a "Fork and Pull" workflow that is standard to GitHub. In git terms, your personal fork is referred to as the "origin" and the actual project's git repository is called "upstream". To keep your personal branch (origin) up to date with the project (upstream), it must be configured within your local working copy.
|
||||
|
||||
- [Contribution Guide]
|
||||
- [MacOS Dev Guide]
|
||||
- [Windows Dev Guide]
|
||||
### Create a fork in GitHub
|
||||
1. Visit https://github.com/kubernetes-sigs/kustomize
|
||||
2. Click the `Fork` button on the top right
|
||||
|
||||
General resources for contributors:
|
||||
### Clone the repository
|
||||
```bash
|
||||
# Clone your repository fork from the previous step
|
||||
git clone --recurse-submodules git@github.com:<your github username>/kustomize.git
|
||||
cd kustomize
|
||||
|
||||
# Configure upstream
|
||||
git remote add upstream https://github.com/kubernetes-sigs/kustomize
|
||||
git remote set-url --push upstream no_push
|
||||
|
||||
# Review git configuration
|
||||
git remote -v
|
||||
```
|
||||
|
||||
### Create a working branch
|
||||
```bash
|
||||
# Fetch changes from upstream master
|
||||
cd kustomize
|
||||
git fetch upstream
|
||||
git checkout master
|
||||
git rebase upstream/master
|
||||
|
||||
# Create your working branch
|
||||
git checkout -b myfeature
|
||||
```
|
||||
|
||||
### Sync your working branch
|
||||
You will need to periodically fetch changes from the `upstream` repository to keep your working branch in sync.
|
||||
```bash
|
||||
cd kustomize
|
||||
git fetch upstream
|
||||
git checkout myfeature
|
||||
git rebase upstream/master
|
||||
```
|
||||
|
||||
### Push to GitHub
|
||||
When your changes are ready for review, push your working branch to your fork on GitHub.
|
||||
```bash
|
||||
cd kustomize
|
||||
git push origin myfeature
|
||||
```
|
||||
|
||||
### Create a Pull Request
|
||||
1. Visit your fork at `https://github.com/<user>/kustomize`
|
||||
2. Click the **Compare & Pull Request** button next to your `myfeature` branch.
|
||||
3. Check out the pull request [process](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md) for more details and advice.
|
||||
|
||||
If you ran `git push` in the previous step, GitHub will return a useful link to create a Pull Request.
|
||||
|
||||
|
||||
### Build Kustomize
|
||||
The [Kustomize Architecture] document describes the respository organization and the kustomize build process.
|
||||
```bash
|
||||
# For go version >= 1.13
|
||||
unset GOPATH
|
||||
unset GO111MODULES
|
||||
|
||||
# Build kustomize binary and install in go bin path
|
||||
cd kustomize
|
||||
make kustomize
|
||||
|
||||
# Run unit tests
|
||||
make test-unit-all
|
||||
|
||||
# Run linter
|
||||
make lint
|
||||
|
||||
# Test examples against HEAD
|
||||
make test-examples-kustomize-against-HEAD
|
||||
|
||||
# Run your development version
|
||||
~/go/bin/kustomize version
|
||||
```
|
||||
|
||||
### General resources for contributors
|
||||
|
||||
- [Contributor License Agreement] - Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests.
|
||||
- [Kubernetes Contributor Guide] - Main contributor documentation.
|
||||
@@ -59,12 +135,144 @@ Kustomize follows the [Kubernetes Community Membership] contributor ladder. Role
|
||||
|
||||
The kyaml module within the Kustomize repo has additional owners following the same ladder.
|
||||
|
||||
Administrative notes:
|
||||
For the kustomize project, we have defined some specific guidelines on each step of the ladder:
|
||||
|
||||
To reach reviewer status, you must:
|
||||
- Have been actively involved in kustomize for 3+ months
|
||||
- Review at least 8 PRs that have been driven through to completion (see the reviewer guide below)
|
||||
- Author at least 5 PRs that have been approved and merged
|
||||
- Be a member of the kubernetes-sigs org. This should not be a blocker though, as once you meet the requirements for reviewer here,
|
||||
the existing kustomize maintainers will be happy to sponsor your request to join the kubernetes-sigs org.
|
||||
- Once you have met the above requirements, you may submit a PR adding yourself to the kustomize reviewers list, with links to your
|
||||
contributions in the description.
|
||||
|
||||
To reach approver status, you must:
|
||||
- Meet all the requirements of a reviewer
|
||||
- Have been actively involved in kustomize for 6+ months
|
||||
- Review at least 15 PRs that have been driven through to completion (see the reviewer guide below)
|
||||
- Authored PRs meeting *either* of the following requirements:
|
||||
- 15 PRs that have been approved and merged
|
||||
- *OR* 10 PRs that have been approved and merged where some were more difficult, required greater thought/design,
|
||||
or built up to larger features/long-term goals.
|
||||
- File 3 issues. This can be any number of things, including but not limited to:
|
||||
- Bugs with kustomize usage that you've found
|
||||
- CI or release improvements
|
||||
- Creating subtasks of a larger feature or project that you are in charge of.
|
||||
- Long term improvements for the health of the project
|
||||
- Triage at least 10 untriaged issues, including at least 1 feature request. The kustomize bug scrub is a great place to get practice with doing this, but you can
|
||||
also follow the triage guide below to get started on your own.
|
||||
- Demonstrate deeper understanding of kustomize goals. This can take many forms and is a bit subjective, but here are a few examples:
|
||||
- saying no to an eschewed feature, instead recommending an alternative solution that is more aligned with the declarative configuration model
|
||||
- active participation in discussion on a feature request issue
|
||||
- filing an issue describing a long term problem and solution aligned with kustomize goals, for example: https://github.com/kubernetes-sigs/kustomize/issues/5140
|
||||
- writing up KEPs for features that will improve the kustomize workflow while being aligned with kustomize goals, for example: https://github.com/kubernetes-sigs/kustomize/pull/4558
|
||||
- Regularly interact with the existing kustomize maintainers, with clear communication about what you are working on or planning to work on. The kustomize
|
||||
maintainers should know who you are and be familiar with your contributions.
|
||||
- If you meet *most* of the above requirements while going above and beyond in a few areas, we will still consider your request to become an approver even
|
||||
if you are missing one or two of the requirements. Please contact the maintainers directly to ask about getting approver status if you fall into this category.
|
||||
- Otherwise, once you meet all the above requirements, you may:
|
||||
- request to be added to the kustomize maintainer meeting that occurs each week with the kustomize PMs.
|
||||
- submit a PR adding yourself to the kustomize approvers list, with links to your contributions in the description.
|
||||
|
||||
To reach owner status, you must:
|
||||
- Meet all the requirements of an approver
|
||||
- Have been actively involved with kustomize for 1+ year
|
||||
- Assisted the current owner in driving the roadmap. This can be explicit or implicit help, such as:
|
||||
- Editing the roadmap directly
|
||||
- Reviewing the roadmap
|
||||
- Providing suggestions for issues or prioritization in meetings that indirectly influence the roadmap
|
||||
- Regularly triage issues and attend the kustomize bug scrub
|
||||
- Regularly review PRs (1-2 a week)
|
||||
- Periodically lead the kustomize bug scrub
|
||||
- Periodically release kustomize (ensuring that there are no release blockers and that release notes are clean)
|
||||
- Be the primary owner or point of contact for a particular project or area of code
|
||||
- Ideally, there should be 2-3 owners at a time. Reach out to the current owners if you are interested in ownership. These
|
||||
requirements are not strict and evaluation is somewhat subjective.
|
||||
|
||||
## Reviewer guide
|
||||
Please watch this talk on how to review code from Tim Hockin: https://www.youtube.com/watch?v=OZVv7-o8i40
|
||||
|
||||
For reviewing PRs in kustomize, we have some specific guidelines:
|
||||
- If the PR is introducing a new feature:
|
||||
- *It must be implementing an issue that has already been triage/accepted or
|
||||
a KEP that has been approved.* If it is not, then request the PR author to first file an issue.
|
||||
- The PR must include thorough tests for the new feature, including unit and integration tests
|
||||
- The code must be clean and readable, with thought given to how we will maintain the code in the future
|
||||
- If the feature requires being broken up into multiple PRs to ease review, the feature should not be exposed to users
|
||||
until the feature is completed in the last PR. For example, while we were building `kustomize localize`, we
|
||||
built the feature almost entirely under the `api` module as a library with all the needed tests. There was no way
|
||||
for users to invoke the localize code until the last PR that actually exposed the `kustomize localize` command in the
|
||||
kustomize binary. This allowed us to continue development of `kustomize localize` without blocking kustomize releases.
|
||||
If this type of development is not possible, then new features requiring multiple PRs should be
|
||||
developed in their own feature branch.
|
||||
- If the PR is introducing a bug fix:
|
||||
- If the PR is not fixing an issue that has already been triage/accepted, follow the triage guide below on bug
|
||||
fixes to decide if this is a PR we want to accept.
|
||||
- The PR should have two distinct commits:
|
||||
- The first commit should add a test demonstrating incorrect behavior
|
||||
- The second commit should include the bug fix
|
||||
- Some sample PRs:
|
||||
- https://github.com/kubernetes-sigs/kustomize/pull/5263/commits
|
||||
- https://github.com/kubernetes-sigs/kustomize/pull/3931/commits
|
||||
- The regression test is absolutely required, and we cannot accept bug fixes without tests.
|
||||
- If the PR is introducing a performance improvement:
|
||||
- The PR description should give an indication of how much the performance is being improved and how we
|
||||
can measure it - benchmark tests are fantastic.
|
||||
- Other PRs (documentation, CI improvements, etc.) should be reviewed based on your best judgment.
|
||||
|
||||
## Triage guide
|
||||
The possible triage labels are listed here: https://github.com/kubernetes-sigs/kustomize/labels?q=triage.
|
||||
|
||||
Triaging a feature request means:
|
||||
- Understand what the user is asking for, and their use case.
|
||||
- Verify that it is not an [eschewed feature](https://kubectl.docs.kubernetes.io/faq/kustomize/eschewedfeatures/#build-time-side-effects-from-cli-args-or-env-variables)
|
||||
- Verify that it is not a duplicate issue.
|
||||
- Look into workarounds. Is there another way that the user can achieve their use case with existing features?
|
||||
- If you are new to this role, prior to leaving a comment on the issue, please bring it to weekly standup
|
||||
for group discussion to make sure that we are all on the same page.
|
||||
- Once you feel ready, you can label it with a triage label. Here's an [example](https://github.com/kubernetes-sigs/kustomize/issues/5049). You can also
|
||||
look at other feature request issues to see how they were triaged and resolved. There are a few different triage labels that you can use, you can see the
|
||||
full list [here](https://github.com/kubernetes-sigs/kustomize/labels?q=triage).
|
||||
|
||||
Triaging a bug means:
|
||||
- First, verify that you can reproduce the issue. If you cannot reproduce the issue or need more information to give
|
||||
it a go, triage it accordingly.
|
||||
- Try to understand if this is really a bug or if this is intended behavior from kustomize. If it seems like intended
|
||||
behavior, do your best to explain to the user why this is the case.
|
||||
- If it seems to be a genuine bug, you can /triage accept the issue. In addition, investigate if there are workarounds or
|
||||
alternative solutions for the user that they can try until the issue gets resolved.
|
||||
|
||||
The triage party for kustomize is here https://cli.triage.k8s.io/s/kustomize and can be a easy way to
|
||||
find issues that have not been triaged yet.
|
||||
|
||||
## Project/Product Managers
|
||||
|
||||
Kustomize will have opportunities to join in a project/product manager role. You can reach out to
|
||||
the existing kustomize maintainers if you are interested in this type of role. Project management work
|
||||
can greatly help supplement your contributions as you climb from reviewer to approver
|
||||
to owner.
|
||||
|
||||
Expectations for this role are:
|
||||
|
||||
- Triage 1 feature request each week, and bring it to weekly stand-up for discussion. Feature
|
||||
requests are issues labeled kind/feature, and you can find them [here](https://github.com/kubernetes-sigs/kustomize/issues?q=is%3Aissue+is%3Aopen+kind+feature+label%3Akind%2Ffeature).
|
||||
Please view the above triage guide for details on how to approach feature request triage.
|
||||
- Monitor the kustomize Slack channel and try to help users if you can. It is a pretty
|
||||
active channel, so responding to 4-5 users per week is sufficient even if some
|
||||
questions go unanswered. If there is an interesting topic or a recurring problem that many
|
||||
users are having, please bring it up in weekly stand-up.
|
||||
- Keeping track of a queue of backlog issues or PRs that are not being actively looked at in any existing project board.
|
||||
- Organizing or reorganizing project tracking boards when it makes sense.
|
||||
|
||||
You will also be asked to help with roadmap planning, deprecation communication, prioritization,
|
||||
and doing research on kustomize usage when appropriate, though these responsibilities will occur less
|
||||
frequently.
|
||||
|
||||
## Administrative notes:
|
||||
|
||||
- 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
|
||||
|
||||
- [Slack channel]
|
||||
|
||||
51
Makefile
51
Makefile
@@ -3,7 +3,7 @@
|
||||
#
|
||||
# Makefile for kustomize CLI and API.
|
||||
|
||||
LATEST_V4_RELEASE=v4.5.6
|
||||
LATEST_RELEASE=v5.3.0
|
||||
|
||||
SHELL := /usr/bin/env bash
|
||||
GOOS = $(shell go env GOOS)
|
||||
@@ -56,26 +56,25 @@ uninstall-local-tools:
|
||||
|
||||
# Build from local source.
|
||||
$(MYGOBIN)/gorepomod:
|
||||
cd cmd/gorepomod; \
|
||||
go install .
|
||||
cd cmd/gorepomod && go install .
|
||||
|
||||
# Build from local source.
|
||||
$(MYGOBIN)/k8scopy:
|
||||
cd cmd/k8scopy; \
|
||||
go install .
|
||||
cd cmd/k8scopy && go install .
|
||||
|
||||
# Build from local source.
|
||||
$(MYGOBIN)/pluginator:
|
||||
cd cmd/pluginator; \
|
||||
go install .
|
||||
cd cmd/pluginator && go install .
|
||||
|
||||
|
||||
# --- Build targets ---
|
||||
|
||||
# Build from local source.
|
||||
$(MYGOBIN)/kustomize: build-kustomize-api
|
||||
cd kustomize; \
|
||||
go install .
|
||||
cd kustomize && go install -ldflags \
|
||||
"-X sigs.k8s.io/kustomize/api/provenance.buildDate=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') \
|
||||
-X sigs.k8s.io/kustomize/api/provenance.version=$(shell git describe --tags --always --dirty)" \
|
||||
.
|
||||
|
||||
kustomize: $(MYGOBIN)/kustomize
|
||||
|
||||
@@ -83,11 +82,11 @@ kustomize: $(MYGOBIN)/kustomize
|
||||
# plugin-to-api compatibility checks.
|
||||
.PHONY: build-kustomize-api
|
||||
build-kustomize-api: $(MYGOBIN)/goimports $(builtinplugins)
|
||||
cd api; $(MAKE) build
|
||||
cd api && $(MAKE) build
|
||||
|
||||
.PHONY: generate-kustomize-api
|
||||
generate-kustomize-api:
|
||||
cd api; $(MAKE) generate
|
||||
cd api && $(MAKE) generate
|
||||
|
||||
|
||||
# --- Verification targets ---
|
||||
@@ -100,18 +99,21 @@ verify-kustomize-repo: \
|
||||
build-non-plugin-all \
|
||||
test-go-mod \
|
||||
test-examples-kustomize-against-HEAD \
|
||||
test-examples-kustomize-against-v4-release
|
||||
test-examples-kustomize-against-latest-release
|
||||
|
||||
# The following target referenced by a file in
|
||||
# https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/kustomize
|
||||
.PHONY: prow-presubmit-check
|
||||
prow-presubmit-check: \
|
||||
install-tools \
|
||||
workspace-sync \
|
||||
generate-kustomize-builtin-plugins \
|
||||
builtin-plugins-diff \
|
||||
test-unit-kustomize-plugins \
|
||||
test-go-mod \
|
||||
build-non-plugin-all \
|
||||
test-examples-kustomize-against-HEAD \
|
||||
test-examples-kustomize-against-v4-release
|
||||
test-examples-kustomize-against-latest-release
|
||||
|
||||
.PHONY: license
|
||||
license: $(MYGOBIN)/addlicense
|
||||
@@ -125,6 +127,10 @@ check-license: $(MYGOBIN)/addlicense
|
||||
lint: $(MYGOBIN)/golangci-lint $(MYGOBIN)/goimports $(builtinplugins)
|
||||
./hack/for-each-module.sh "make lint"
|
||||
|
||||
.PHONY: apidiff
|
||||
apidiff: $(MYGOBIN)/go-apidiff ## Run the go-apidiff to verify any API differences compared with origin/master
|
||||
go-apidiff master --compare-imports --print-compatible --repo-path=.
|
||||
|
||||
.PHONY: test-unit-all
|
||||
test-unit-all: \
|
||||
test-unit-non-plugin \
|
||||
@@ -133,14 +139,14 @@ test-unit-all: \
|
||||
# This target is used by our Github Actions CI to run unit tests for all non-plugin modules in multiple GOOS environments.
|
||||
.PHONY: test-unit-non-plugin
|
||||
test-unit-non-plugin:
|
||||
./hack/for-each-module.sh "make test" "./plugin/*" 15
|
||||
./hack/for-each-module.sh "make test" "./plugin/*" 20
|
||||
|
||||
.PHONY: build-non-plugin-all
|
||||
build-non-plugin-all:
|
||||
./hack/for-each-module.sh "make build" "./plugin/*" 15
|
||||
./hack/for-each-module.sh "make build" "./plugin/*" 20
|
||||
|
||||
.PHONY: test-unit-kustomize-plugins
|
||||
test-unit-kustomize-plugins:
|
||||
test-unit-kustomize-plugins: build-kustomize-external-go-plugin
|
||||
./hack/testUnitKustomizePlugins.sh
|
||||
|
||||
.PHONY: functions-examples-all
|
||||
@@ -152,7 +158,7 @@ functions-examples-all:
|
||||
done
|
||||
|
||||
test-go-mod:
|
||||
./hack/for-each-module.sh "go list -m -json all > /dev/null && go mod tidy -v"
|
||||
./hack/for-each-module.sh "go mod tidy -v"
|
||||
|
||||
.PHONY:
|
||||
verify-kustomize-e2e: $(MYGOBIN)/mdrip $(MYGOBIN)/kind
|
||||
@@ -169,10 +175,15 @@ test-examples-kustomize-against-HEAD: $(MYGOBIN)/kustomize $(MYGOBIN)/mdrip
|
||||
./hack/testExamplesAgainstKustomize.sh HEAD
|
||||
|
||||
.PHONY:
|
||||
test-examples-kustomize-against-v4-release: $(MYGOBIN)/mdrip
|
||||
./hack/testExamplesAgainstKustomize.sh v4@$(LATEST_V4_RELEASE)
|
||||
|
||||
test-examples-kustomize-against-latest-release: $(MYGOBIN)/mdrip
|
||||
./hack/testExamplesAgainstKustomize.sh v5@$(LATEST_RELEASE)
|
||||
|
||||
# Pushes dependencies in the go.work file back to go.mod files of each workspace module.
|
||||
.PHONY: workspace-sync
|
||||
workspace-sync:
|
||||
go work sync
|
||||
./hack/doGoMod.sh tidy
|
||||
|
||||
# --- Cleanup targets ---
|
||||
.PHONY: clean
|
||||
clean: clean-kustomize-external-go-plugin uninstall-tools
|
||||
|
||||
@@ -14,6 +14,7 @@ include $(KUSTOMIZE_ROOT)/Makefile-tools.mk
|
||||
.PHONY: lint test fix fmt tidy vet build
|
||||
|
||||
lint: $(MYGOBIN)/golangci-lint
|
||||
$(MYGOBIN)/golangci-lint cache clean # Workaround for https://github.com/golangci/golangci-lint/issues/3228
|
||||
$(MYGOBIN)/golangci-lint \
|
||||
-c $$KUSTOMIZE_ROOT/.golangci.yml \
|
||||
--path-prefix $(shell pwd | sed -E 's|(.*\/kustomize)/(.*)|\2|') \
|
||||
|
||||
@@ -89,9 +89,27 @@ $(pGen)/%.go: $(MYGOBIN)/pluginator $(MYGOBIN)/goimports
|
||||
$(MYGOBIN)/goimports -w $*.go \
|
||||
)
|
||||
|
||||
# Target is for debugging.
|
||||
# Generate builtin plugins
|
||||
.PHONY: generate-kustomize-builtin-plugins
|
||||
generate-kustomize-builtin-plugins: $(builtinplugins)
|
||||
generate-kustomize-builtin-plugins: $(builtplugins)
|
||||
for plugin in $(abspath $(wildcard $(pSrc)/*)); do \
|
||||
echo "generating $${plugin} ..."; \
|
||||
set -e; \
|
||||
cd $${plugin}; \
|
||||
go generate .; \
|
||||
done
|
||||
|
||||
# Check for diff by comparing current revision of generated plugins on HEAD and newly generated plugins on local branch,
|
||||
# If diff is found, throw error code 1
|
||||
.PHONY: builtin-plugins-diff
|
||||
builtin-plugins-diff: $(builtplugins)
|
||||
for file in $(abspath $(builtinplugins)); do \
|
||||
echo "Checking for diff... $${file}" ; \
|
||||
set -e ; \
|
||||
if [ "`git diff $${file} | wc -c`" -gt 0 ]; then\
|
||||
echo "Error(1): diff found on $${file}"; exit 1; \
|
||||
fi \
|
||||
done
|
||||
|
||||
.PHONY: build-kustomize-external-go-plugin
|
||||
build-kustomize-external-go-plugin:
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
# Copyright 2022 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
GOLANGCI_LINT_VERSION=v1.50.1
|
||||
|
||||
GOOS = $(shell go env GOOS)
|
||||
GOARCH = $(shell go env GOARCH)
|
||||
MYGOBIN = $(shell go env GOBIN)
|
||||
ifeq ($(MYGOBIN),)
|
||||
MYGOBIN = $(shell go env GOPATH)/bin
|
||||
endif
|
||||
export PATH := $(MYGOBIN):$(PATH)
|
||||
|
||||
REPO_ROOT=$(shell git rev-parse --show-toplevel)
|
||||
|
||||
# determines whether to run tests that only behave locally; can be overridden by override variable
|
||||
export IS_LOCAL = false
|
||||
|
||||
@@ -18,8 +20,7 @@ install-out-of-tree-tools: \
|
||||
$(MYGOBIN)/golangci-lint \
|
||||
$(MYGOBIN)/helmV3 \
|
||||
$(MYGOBIN)/mdrip \
|
||||
$(MYGOBIN)/stringer \
|
||||
$(MYGOBIN)/goimports
|
||||
$(MYGOBIN)/stringer
|
||||
|
||||
.PHONY: uninstall-out-of-tree-tools
|
||||
uninstall-out-of-tree-tools:
|
||||
@@ -29,67 +30,61 @@ uninstall-out-of-tree-tools:
|
||||
rm -f $(MYGOBIN)/mdrip
|
||||
rm -f $(MYGOBIN)/stringer
|
||||
|
||||
.PHONY: $(MYGOBIN)/golangci-lint
|
||||
$(MYGOBIN)/golangci-lint:
|
||||
go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)
|
||||
cd $(REPO_ROOT)/hack && go install github.com/golangci/golangci-lint/cmd/golangci-lint
|
||||
|
||||
.PHONY: $(MYGOBIN)/mdrip
|
||||
$(MYGOBIN)/mdrip:
|
||||
go install github.com/monopole/mdrip@v1.0.2
|
||||
cd $(REPO_ROOT)/hack && go install github.com/monopole/mdrip
|
||||
|
||||
.PHONY: $(MYGOBIN)/stringer
|
||||
$(MYGOBIN)/stringer:
|
||||
go install golang.org/x/tools/cmd/stringer@latest
|
||||
cd $(REPO_ROOT)/hack && go install golang.org/x/tools/cmd/stringer
|
||||
|
||||
.PHONY: $(MYGOBIN)/goimports
|
||||
$(MYGOBIN)/goimports:
|
||||
go install golang.org/x/tools/cmd/goimports@latest
|
||||
cd $(REPO_ROOT)/hack && go install golang.org/x/tools/cmd/goimports
|
||||
|
||||
.PHONY: $(MYGOBIN)/mdtogo
|
||||
$(MYGOBIN)/mdtogo:
|
||||
go install sigs.k8s.io/kustomize/cmd/mdtogo@latest
|
||||
cd $(REPO_ROOT)/hack && go install sigs.k8s.io/kustomize/cmd/mdtogo
|
||||
|
||||
.PHONY: $(MYGOBIN)/addlicense
|
||||
$(MYGOBIN)/addlicense:
|
||||
go install github.com/google/addlicense@latest
|
||||
|
||||
$(MYGOBIN)/goreleaser:
|
||||
go install github.com/goreleaser/goreleaser@v0.179.0 # https://github.com/kubernetes-sigs/kustomize/issues/4542
|
||||
cd $(REPO_ROOT)/hack && go install github.com/google/addlicense
|
||||
|
||||
.PHONY: $(MYGOBIN)/kind
|
||||
$(MYGOBIN)/kind:
|
||||
( \
|
||||
set -e; \
|
||||
d=$(shell mktemp -d); cd $$d; \
|
||||
wget -O ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-$(GOOS)-$(GOARCH); \
|
||||
chmod +x ./kind; \
|
||||
mv ./kind $(MYGOBIN); \
|
||||
rm -rf $$d; \
|
||||
)
|
||||
cd $(REPO_ROOT)/hack && go install sigs.k8s.io/kind
|
||||
|
||||
# linux only.
|
||||
.PHONY: $(MYGOBIN)/controller-gen
|
||||
$(MYGOBIN)/controller-gen:
|
||||
cd $(REPO_ROOT)/hack && go install sigs.k8s.io/controller-tools/cmd/controller-gen
|
||||
|
||||
.PHONY: $(MYGOBIN)/embedmd
|
||||
$(MYGOBIN)/embedmd:
|
||||
cd $(REPO_ROOT)/hack && go install github.com/campoy/embedmd
|
||||
|
||||
.PHONY: $(MYGOBIN)/go-bindata
|
||||
$(MYGOBIN)/go-bindata:
|
||||
cd $(REPO_ROOT)/hack && go install github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
|
||||
.PHONY: $(MYGOBIN)/go-apidiff
|
||||
$(MYGOBIN)/go-apidiff:
|
||||
cd $(REPO_ROOT)/hack && go install github.com/joelanford/go-apidiff
|
||||
|
||||
.PHONY: $(MYGOBIN)/gh
|
||||
$(MYGOBIN)/gh:
|
||||
( \
|
||||
set -e; \
|
||||
d=$(shell mktemp -d); cd $$d; \
|
||||
tgzFile=gh_1.0.0_$(GOOS)_$(GOARCH).tar.gz; \
|
||||
wget https://github.com/cli/cli/releases/download/v1.0.0/$$tgzFile; \
|
||||
tar -xvzf $$tgzFile; \
|
||||
mv gh_1.0.0_$(GOOS)_$(GOARCH)/bin/gh $(MYGOBIN)/gh; \
|
||||
rm -rf $$d \
|
||||
)
|
||||
cd $(REPO_ROOT)/hack && go install github.com/cli/cli/cmd/gh
|
||||
|
||||
# linux only.
|
||||
# This is for testing an example plugin that
|
||||
# uses kubeval for validation.
|
||||
# Don't want to add a hard dependence in go.mod file
|
||||
# to github.com/instrumenta/kubeval.
|
||||
# Instead, download the binary.
|
||||
.PHONY: $(MYGOBIN)/kubeval
|
||||
$(MYGOBIN)/kubeval:
|
||||
( \
|
||||
set -e; \
|
||||
d=$(shell mktemp -d); cd $$d; \
|
||||
wget https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-$(GOOS)-$(GOARCH).tar.gz; \
|
||||
tar xf kubeval-$(GOOS)-$(GOARCH).tar.gz; \
|
||||
mv kubeval $(MYGOBIN); \
|
||||
rm -rf $$d; \
|
||||
)
|
||||
cd $(REPO_ROOT)/hack && go install github.com/instrumenta/kubeval
|
||||
|
||||
# Helm V3 differs from helm V2; downloading it to provide coverage for the
|
||||
# chart inflator plugin under helm v3.
|
||||
.PHONY: $(MYGOBIN)/helmV3
|
||||
$(MYGOBIN)/helmV3:
|
||||
( \
|
||||
set -e; \
|
||||
|
||||
1
OWNERS
1
OWNERS
@@ -1,6 +1,5 @@
|
||||
# See https://github.com/kubernetes/community/blob/master/community-membership.md
|
||||
approvers:
|
||||
- kustomize-approvers
|
||||
|
||||
reviewers:
|
||||
- kustomize-reviewers
|
||||
|
||||
@@ -3,29 +3,37 @@
|
||||
aliases:
|
||||
kustomize-owners:
|
||||
- knverey
|
||||
- natasha41575
|
||||
- koba1t
|
||||
kustomize-approvers:
|
||||
- knverey
|
||||
- natasha41575
|
||||
- koba1t
|
||||
- varshaprasad96
|
||||
kustomize-reviewers:
|
||||
- knverey
|
||||
- natasha41575
|
||||
- yuwenma
|
||||
- annasong20
|
||||
- koba1t
|
||||
- stormqueen1990
|
||||
- varshaprasad96
|
||||
- ncapps
|
||||
|
||||
kyaml-approvers:
|
||||
- mengqiy
|
||||
- mortent
|
||||
- phanimarupaka
|
||||
kyaml-reviewers:
|
||||
- mengqiy
|
||||
- mortent
|
||||
- phanimarupaka
|
||||
docs-approvers:
|
||||
- ncapps
|
||||
docs-reviewers:
|
||||
- ncapps
|
||||
|
||||
emeritus-approvers:
|
||||
- liujingfang1
|
||||
- Shell32-Natsu
|
||||
- justinsb
|
||||
- monopole
|
||||
- pwittrock
|
||||
commands-approvers:
|
||||
- stormqueen1990
|
||||
commands-reviewers:
|
||||
- stormqueen1990
|
||||
|
||||
# emeritus:
|
||||
# - liujingfang1
|
||||
# - Shell32-Natsu
|
||||
# - justinsb
|
||||
# - monopole
|
||||
# - pwittrock
|
||||
# - mengqiy
|
||||
# - mortent
|
||||
# - phanimarupaka
|
||||
# - natasha41575
|
||||
# - annasong20
|
||||
# - yuwenma
|
||||
|
||||
92
README.md
92
README.md
@@ -20,6 +20,14 @@ This tool is sponsored by [sig-cli] ([KEP]).
|
||||
|
||||
## kubectl integration
|
||||
|
||||
To find the kustomize version embedded in recent versions of kubectl, run `kubectl version`:
|
||||
|
||||
```sh
|
||||
> kubectl version --short --client
|
||||
Client Version: v1.26.0
|
||||
Kustomize Version: v4.5.7
|
||||
```
|
||||
|
||||
The kustomize build flow at [v2.0.3] was added
|
||||
to [kubectl v1.14][kubectl announcement]. The kustomize
|
||||
flow in kubectl remained frozen at v2.0.3 until kubectl v1.21,
|
||||
@@ -28,11 +36,16 @@ be updated on a regular basis going forward, and such updates
|
||||
will be reflected in the Kubernetes release notes.
|
||||
|
||||
| Kubectl version | Kustomize version |
|
||||
| --- | --- |
|
||||
| < v1.14 | n/a |
|
||||
| v1.14-v1.20 | v2.0.3 |
|
||||
| v1.21 | v4.0.5 |
|
||||
| v1.22 | v4.2.0 |
|
||||
| --------------- | ----------------- |
|
||||
| < v1.14 | n/a |
|
||||
| v1.14-v1.20 | v2.0.3 |
|
||||
| v1.21 | v4.0.5 |
|
||||
| v1.22 | v4.2.0 |
|
||||
| v1.23 | v4.4.1 |
|
||||
| v1.24 | v4.5.4 |
|
||||
| v1.25 | v4.5.7 |
|
||||
| v1.26 | v4.5.7 |
|
||||
| v1.27 | v5.0.1 |
|
||||
|
||||
[v2.0.3]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v2.0.3
|
||||
[#2506]: https://github.com/kubernetes-sigs/kustomize/issues/2506
|
||||
@@ -55,7 +68,37 @@ This file should declare those resources, and any
|
||||
customization to apply to them, e.g. _add a common
|
||||
label_.
|
||||
|
||||
![base image][imageBase]
|
||||
```
|
||||
|
||||
base: kustomization + resources
|
||||
|
||||
kustomization.yaml deployment.yaml service.yaml
|
||||
+---------------------------------------------+ +-------------------------------------------------------+ +-----------------------------------+
|
||||
| apiVersion: kustomize.config.k8s.io/v1beta1 | | apiVersion: apps/v1 | | apiVersion: v1 |
|
||||
| kind: Kustomization | | kind: Deployment | | kind: Service |
|
||||
| commonLabels: | | metadata: | | metadata: |
|
||||
| app: myapp | | name: myapp | | name: myapp |
|
||||
| resources: | | spec: | | spec: |
|
||||
| - deployment.yaml | | selector: | | selector: |
|
||||
| - service.yaml | | matchLabels: | | app: myapp |
|
||||
| configMapGenerator: | | app: myapp | | ports: |
|
||||
| - name: myapp-map | | template: | | - port: 6060 |
|
||||
| literals: | | metadata: | | targetPort: 6060 |
|
||||
| - KEY=value | | labels: | +-----------------------------------+
|
||||
+---------------------------------------------+ | app: myapp |
|
||||
| spec: |
|
||||
| containers: |
|
||||
| - name: myapp |
|
||||
| image: myapp |
|
||||
| resources: |
|
||||
| limits: |
|
||||
| memory: "128Mi" |
|
||||
| cpu: "500m" |
|
||||
| ports: |
|
||||
| - containerPort: 6060 |
|
||||
+-------------------------------------------------------+
|
||||
|
||||
```
|
||||
|
||||
File structure:
|
||||
|
||||
@@ -91,20 +134,41 @@ Manage traditional [variants] of a configuration - like
|
||||
_development_, _staging_ and _production_ - using
|
||||
[overlays] that modify a common [base].
|
||||
|
||||
![overlay image][imageOverlay]
|
||||
```
|
||||
|
||||
overlay: kustomization + patches
|
||||
|
||||
kustomization.yaml replica_count.yaml cpu_count.yaml
|
||||
+-----------------------------------------------+ +-------------------------------+ +------------------------------------------+
|
||||
| apiVersion: kustomize.config.k8s.io/v1beta1 | | apiVersion: apps/v1 | | apiVersion: apps/v1 |
|
||||
| kind: Kustomization | | kind: Deployment | | kind: Deployment |
|
||||
| commonLabels: | | metadata: | | metadata: |
|
||||
| variant: prod | | name: myapp | | name: myapp |
|
||||
| resources: | | spec: | | spec: |
|
||||
| - ../../base | | replicas: 80 | | template: |
|
||||
| patches: | +-------------------------------+ | spec: |
|
||||
| - path: replica_count.yaml | | containers: |
|
||||
| - path: cpu_count.yaml | | - name: myapp |
|
||||
+-----------------------------------------------+ | resources: |
|
||||
| limits: |
|
||||
| memory: "128Mi" |
|
||||
| cpu: "7000m" |
|
||||
+------------------------------------------+
|
||||
```
|
||||
|
||||
|
||||
File structure:
|
||||
> ```
|
||||
> ~/someApp
|
||||
> ├── base
|
||||
> │ ├── deployment.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── service.yaml
|
||||
> │ ├── deployment.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── service.yaml
|
||||
> └── overlays
|
||||
> ├── development
|
||||
> │ ├── cpu_count.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── replica_count.yaml
|
||||
> │ ├── cpu_count.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── replica_count.yaml
|
||||
> └── production
|
||||
> ├── cpu_count.yaml
|
||||
> ├── kustomization.yaml
|
||||
@@ -158,8 +222,6 @@ is governed by the [Kubernetes Code of Conduct].
|
||||
[applied]: https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#apply
|
||||
[base]: https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#base
|
||||
[declarative configuration]: https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#declarative-application-management
|
||||
[imageBase]: images/base.jpg
|
||||
[imageOverlay]: images/overlay.jpg
|
||||
[kubectl announcement]: https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement
|
||||
[kubernetes documentation]: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
|
||||
[kubernetes style]: https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#kubernetes-style-object
|
||||
|
||||
241
ROADMAP.md
241
ROADMAP.md
@@ -1,112 +1,185 @@
|
||||
# Kustomize roadmap 2022
|
||||
# Kustomize roadmap 2023-2024
|
||||
|
||||
Presented at the [January 26, 2022, SIG-CLI meeting](https://youtu.be/l2plzJ9MRlk?t=1321)
|
||||
This document describes the items that we hope to make progress on over the next
|
||||
1 year (H2 2023 and H1 2024). Take this roadmap as more of what we hope to achieve
|
||||
rather than what we promise to achieve, as some items in this doc are highly dependent
|
||||
on the success that we have on-ramping new contributors to the project, and other
|
||||
items will depend on external contributions, which can vary.
|
||||
|
||||
kustomize maintainers: @knverey, @natasha41575
|
||||
If you are interested in contributing to a particular area, you can look through
|
||||
the project board for that area and assign yourself to one of the issues. It is
|
||||
recommended to start with smaller issues to ramp up on the project before starting
|
||||
to tackle larger issues.
|
||||
|
||||
[Objective: Improve contributor community](#objective-improve-contributor-community)
|
||||
Project boards:
|
||||
https://github.com/orgs/kubernetes-sigs/projects/50
|
||||
https://github.com/orgs/kubernetes-sigs/projects/51
|
||||
https://github.com/orgs/kubernetes-sigs/projects/52
|
||||
https://github.com/orgs/kubernetes-sigs/projects/53
|
||||
https://github.com/orgs/kubernetes-sigs/projects/54
|
||||
|
||||
[Objective: Improve end-user experience](#objective-improve-end-user-experience)
|
||||
## Kustomize contributors (at time of writing):
|
||||
|
||||
[Objective: Improve extension experience](#objective-improve-extension-experience)
|
||||
kustomize owner: @natasha41575
|
||||
|
||||
## Objective: Improve contributor community
|
||||
kustomize maintainers: @annasong20, @koba1t
|
||||
|
||||
**_WHO: End user who also contributes source code._**
|
||||
|
||||
Top priority:
|
||||
|
||||
- Kustomization v1 (also end-user impact) ([PROJECT](https://github.com/kubernetes-sigs/kustomize/projects/12))
|
||||
- Remove the following fields:
|
||||
- [vars](https://github.com/kubernetes-sigs/kustomize/issues/2052)
|
||||
- [patchesJson6902, patchesStrategicMerge (consolidate on \`patches)](https://github.com/kubernetes-sigs/kustomize/issues/4376)
|
||||
- [helmChartInflationGenerator, helmCharts, helmGlobals](https://github.com/kubernetes-sigs/kustomize/issues/4401)
|
||||
- all long-deprecated fields in Kustomization v1 such as \`bases\` and those being accommodate by kustomize edit \[[see code snippet](https://github.com/kubernetes-sigs/kustomize/blob/ee4b7847f0beb6c0d2070673b10f23f7b3e92e82/api/types/fix.go#L15)\]
|
||||
- Ensure that \`kustomize edit fix\` handles migrations for all those, and that anything it changes is not still present in v1.
|
||||
- [Add reorder field](https://github.com/kubernetes-sigs/kustomize/issues/3913). Default should be FIFO and legacy should also be supported (could add alphabetic and custom sort support eventually). Replaces -reorder flag.
|
||||
- [Reconcile openapi and crds field](https://github.com/kubernetes-sigs/kustomize/issues/3944)
|
||||
- [Consider deprecating configurations field](https://github.com/kubernetes-sigs/kustomize/issues/3945) (old, pre-plugin, pre-openapi global configuration)
|
||||
- [Add a field to enable the managedby label](https://github.com/kubernetes-sigs/kustomize/issues/4047)
|
||||
|
||||
Second priority:
|
||||
|
||||
- Improve contributor documentation
|
||||
- [Instructions to upgrade kustomize-in-kubectl](https://github.com/kubernetes-sigs/kustomize/issues/3951)
|
||||
|
||||
Also very valuable to the project:
|
||||
|
||||
- [Improve the release process](https://github.com/kubernetes-sigs/kustomize/issues/3952) to support regular biweekly releases [PROJECT](https://github.com/kubernetes-sigs/kustomize/projects/7)
|
||||
- Release sigs.k8s.io/kustomize/api v1.0.0 [PROJECT](https://github.com/kubernetes-sigs/kustomize/projects/5)
|
||||
- [Reduce the public surface of the API module](https://github.com/kubernetes-sigs/kustomize/issues/3942)
|
||||
- [Vendor all transitive deps](https://github.com/kubernetes-sigs/kustomize/issues/3706). Since kustomize is in kubectl, we must do as kubectl does to manage deps, exposing new transitive deps in code review.
|
||||
- Project administration
|
||||
- [Rename master branch to main](https://github.com/kubernetes-sigs/kustomize/issues/3954)
|
||||
kustomize contributors: @varshaprasad96
|
||||
|
||||
|
||||
# H2 2023
|
||||
|
||||
## Objective: Improve end-user experience
|
||||
## Goal: Create kustomize leadership and contributor playbooks
|
||||
|
||||
**_WHO: End user that wants kustomize build artifacts (binaries, containers)._**
|
||||
Contributors: natasha41575, annasong20
|
||||
|
||||
Top priorities:
|
||||
Priority: High
|
||||
|
||||
- Bug fixes:
|
||||
- Fix bugs in basic anchor support: [issue query](https://github.com/kubernetes-sigs/kustomize/issues?q=is%3Aopen+is%3Aissue+label%3Aarea%2Fanchors)
|
||||
- integer keys support: [#3446](https://github.com/kubernetes-sigs/kustomize/issues/3446)
|
||||
- kyaml not respecting \`$patch replace|retainKeys\`: [#2037](https://github.com/kubernetes-sigs/kustomize/issues/2037)
|
||||
- kustomize removing quotes from namespace field values: [#4146](https://github.com/kubernetes-sigs/kustomize/issues/4146)
|
||||
- Kustomize doesn’t support metadata.generateName: [#641](https://github.com/kubernetes-sigs/kustomize/issues/641)
|
||||
- Send kustomize CLI version number into kubectl ([kubectl issue](https://github.com/kubernetes/kubectl/issues/797) / [kustomize issue](https://github.com/kubernetes-sigs/kustomize/issues/1424))
|
||||
- Kustomize performance investigations/improvements [PROJECT](https://github.com/kubernetes-sigs/kustomize/projects/13)
|
||||
- [Support generic resource references in name reference tracking](https://github.com/kubernetes-sigs/kustomize/issues/3418)
|
||||
- [KEP 4267: retain the resource origin and transformer data in annotations](https://github.com/kubernetes-sigs/kustomize/pull/4267)
|
||||
Effort: Medium
|
||||
|
||||
Secondary priorities:
|
||||
In the past, when the leads stopped contributing (for various reasons, not covered here)
|
||||
in various kubernetes projects, it left a wide hole that few could easily fill,
|
||||
leaving the remaining leads in a bad position and the project understaffed. We should assume
|
||||
that we will need to onboard new maintainers in the future, and should have playbooks
|
||||
for doing so. As we grow the contributor base in kustomize, we will build these playbooks for
|
||||
those who are contributing and those who are looking to grow into kustomize leaders.
|
||||
To ensure the long term health and stability of the project, we should have:
|
||||
|
||||
- kustomize cli v5 ([PROJECT](https://github.com/kubernetes-sigs/kustomize/projects/14))
|
||||
- [Drop the --reorder flag](https://github.com/kubernetes-sigs/kustomize/issues/3947)
|
||||
- [Graduate cfg read-only commands out of alpha](https://github.com/kubernetes-sigs/kustomize/issues/4090).
|
||||
- [Drop the –enable-managedby-label](https://github.com/kubernetes-sigs/kustomize/issues/4047)
|
||||
- Drop old plugin-related fields in favor of [the Catalog-style fields](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2906-kustomize-function-catalog).
|
||||
- [Drop the helm flags](https://github.com/kubernetes-sigs/kustomize/issues/4401)
|
||||
- [Confusion around namespace replacement](https://github.com/kubernetes-sigs/kustomize/issues/880).
|
||||
- On-boarding guides for new contributors
|
||||
- Clear guidelines for how to climb the kustomize ladder from contributor to approver to owner
|
||||
- A plan (maybe a schedule) for future kustomize cohorts
|
||||
- A succession plan, in case the current kustomize leads ever decide to step down
|
||||
|
||||
Also very valuable to the project:
|
||||
## Goal: Onboard 2-5 new contributors to kustomize
|
||||
|
||||
- [Overinclusion of root directory error in error messages](https://github.com/kubernetes-sigs/kustomize/issues/4348)
|
||||
- [Add kustomize localize command](https://github.com/kubernetes-sigs/kustomize/issues/3980)
|
||||
- [Fix Windows support in test suite](https://github.com/kubernetes-sigs/kustomize/issues/4001)
|
||||
- Improve end-user documentation [PROJECT](https://github.com/kubernetes-sigs/kustomize/projects/9)
|
||||
Contributors: natasha41575, annasong20, koba1t
|
||||
|
||||
Priority: High
|
||||
|
||||
## Objective: Improve extension experience
|
||||
Effort: High
|
||||
|
||||
**_WHO: Plugin developers: end users who extend kustomize, but don’t think about internals._**
|
||||
In order to make progress on kustomize goals in the future, we need to increase the
|
||||
level of staffing on kustomize. We should leverage community contributions to keep kustomize
|
||||
healthy and making progress.
|
||||
|
||||
This objective is described in detail in the [Kustomize Plugin Graduation KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2953-kustomize-plugin-graduation) / [PROJECT](https://github.com/kubernetes-sigs/kustomize/projects/15) .
|
||||
The primary means in which we will try to find new kustomize contributors is through the new kustomize
|
||||
maintainer training cohort. We will lead a group of ~20 kubernetes community members through a 3-6 month
|
||||
training program, involving talk sessions, bug scrubs, issue triage, PR reviews, and coding projects for
|
||||
each member.
|
||||
|
||||
Top priorities:
|
||||
See [our call for help](https://groups.google.com/a/kubernetes.io/g/dev/c/M5OphEVsv5o/m/zc6G4H15AAAJ) for more
|
||||
specific details about the program.
|
||||
|
||||
- Fix core usability issues with KRM Function extensions:
|
||||
- [Better errors for function config failures](https://github.com/kubernetes-sigs/kustomize/issues/4398)
|
||||
- [Container KRM Mounts are not mounting via function parameters](https://github.com/kubernetes-sigs/kustomize/issues/4290)
|
||||
- [Resolution of local file references in extensions transformer configuration](https://github.com/kubernetes-sigs/kustomize/issues/4154)
|
||||
- [Do not silently ignore plugins when config has typo](https://github.com/kubernetes-sigs/kustomize/issues/4399)
|
||||
- [KRM Exec Function can't locate executable when referencing a base](https://github.com/kubernetes-sigs/kustomize/issues/4347)
|
||||
- Once core usability issues are fixed, [deprecate legacy exec and Go plugin support](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2953-kustomize-plugin-graduation)
|
||||
- [Catalog KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2906-kustomize-function-catalog)
|
||||
The effort from existing kustomize maintainers here will be to:
|
||||
- Organize the cohort, so that each cohort member feels productive and understands what they should work on
|
||||
- Align motivation of the cohort members with the work that we assign to them.
|
||||
- Review PRs from cohort members in a timely manner.
|
||||
- Be the point(s) of contact for questions/escalations
|
||||
- Lead weekly stand-ups and monthly bug scrubs
|
||||
|
||||
Secondary priorities:
|
||||
At the end of all this, if we have a small team of contributors to kustomize, who understand its founding
|
||||
philosophy and intentions, we should be able to keep the project up to date.
|
||||
|
||||
- [Remove Starlark support](https://github.com/kubernetes-sigs/kustomize/issues/4349)
|
||||
- [Composition KEP](https://github.com/kubernetes/enhancements/pull/2300). The implementation is complete in [#4223](https://github.com/kubernetes-sigs/kustomize/pull/4323), but depends on:
|
||||
- [Convert resources and components to be backed by a reusable generator](https://github.com/kubernetes-sigs/kustomize/issues/4402)
|
||||
- [Enable explicitly invoked transformers to use default fieldSpecs](https://github.com/kubernetes-sigs/kustomize/issues/4404)
|
||||
- [Enable built-in generators to be used in the transformers field ](https://github.com/kubernetes-sigs/kustomize/issues/4403)
|
||||
## Goal: Improve kustomize extensibility through KRM functions and CRD support
|
||||
|
||||
Contributors: koba1t, varshaprasad96, external contributors
|
||||
|
||||
Also very valuable to the project:
|
||||
Priority: High
|
||||
|
||||
- [Improve docs for kyaml libraries](https://github.com/kubernetes-sigs/kustomize/issues/3950), especially by adding examples.
|
||||
- [Create a reserved field for plugin runtime information](https://github.com/kubernetes-sigs/kustomize/issues/4405)
|
||||
- [Develop new standard process for implementing builtin transformers](https://github.com/kubernetes-sigs/kustomize/issues/4400)
|
||||
Effort: High
|
||||
|
||||
Project board: https://github.com/orgs/kubernetes-sigs/projects/53/views/1
|
||||
|
||||
For a long time, we have supported KRM functions as the proper way to implement custom generators and transformers.
|
||||
However, due to limited staffing, we have been unable to drive this feature out of alpha in kustomize. The two
|
||||
main features which we hope to make progress on are Composition and Catalog, two long-standing proposals for which
|
||||
numerous users have been waiting for a long time. There are several open issues
|
||||
regarding KRM functions where our long-term answer has been these two features, but users have been hearing about them
|
||||
for over a year without seeing any progress. If we can implement them, they will vastly improve usability and security
|
||||
of KRM functions.
|
||||
|
||||
One item that falls under this category that does not currently have a contributor is improving CRD support.
|
||||
Currently, it is difficult to use CRDs properly, as there are three different fields (configurations, openapi, and crds)
|
||||
where users have to input their CRD configuration. We need to consolidate these fields into one easy to use feature to
|
||||
support CRDs. If you are interested in putting together a design proposal for how to tackle this task, please reach
|
||||
out to the kustomize maintainers.
|
||||
|
||||
# H1 2024
|
||||
|
||||
## Goal: Improve the kustomize documentation
|
||||
|
||||
Contributors: annasong20, external contributions
|
||||
|
||||
Priority: High
|
||||
|
||||
Effort: High
|
||||
|
||||
Project board: https://github.com/orgs/kubernetes-sigs/projects/50
|
||||
|
||||
The kustomize documentation is currently fragmented, out of date, and lacks examples to fully understand its value.
|
||||
We have had a "docs project" for a long time; we need to prioritize implementing it so that the documentation is in
|
||||
one place, easy to find, and helps new users get started more easily. Some outcomes from this project should be:
|
||||
|
||||
- A single, unified website hosted on kustomize.io
|
||||
- Updated information architecture, and a plan to keep it up to date
|
||||
- End to end examples of using kustomize, including complex use cases
|
||||
|
||||
## Goal: Fix core usability bugs in kustomize
|
||||
|
||||
Contributors: external contributions
|
||||
|
||||
Priority: High
|
||||
|
||||
Effort: High
|
||||
|
||||
Project board: https://github.com/orgs/kubernetes-sigs/projects/51
|
||||
|
||||
There are several core usability issues that block some users from adopting kustomize features or in
|
||||
some base block users from using kustomize entirely. These issues range from small bugs with workable but
|
||||
inconvenient workarounds, to enormous feature gaps.
|
||||
|
||||
As part of this goal, we should work toward reducing the number of such issues that we have, making
|
||||
kustomize work more smoothly and predictably, and be usable for a larger range of users.
|
||||
|
||||
There are a lot of important issues in this project, but the biggest and highest priority one is that
|
||||
kustomize doesn't currently support metadata.GenerateName. Unfortunately, we don't currently have anyone
|
||||
actively working on this issue, we would need an external contributor to reach out to the kustomize
|
||||
maintainers to pick it up.
|
||||
|
||||
## Goal: Improve kustomize CI, release, & security patch processes
|
||||
|
||||
Contributors: external contributions
|
||||
|
||||
Priority: Medium
|
||||
|
||||
Effort: High
|
||||
|
||||
Project board: https://github.com/orgs/kubernetes-sigs/projects/54
|
||||
|
||||
The kustomize release process is currently done on-demand and is strictly linear. This means that if we find a CVE,
|
||||
we are forced to release the next version of kustomize ASAP, and we are required to release every PR that has merged
|
||||
since the last release. This can put us in a sticky situation if we have a breaking change that we are
|
||||
not ready to release yet, but we need a patch quickly.
|
||||
|
||||
We should try to improve the kustomize release process so that we can release frequently, reliably, and with some
|
||||
flexibility. The outcome of this effort should be:
|
||||
|
||||
- kustomize is released on a regular cadence (biweekly or monthly)
|
||||
- kustomize is able to separate patch and feature releases, so that we can fix CVEs without needing to release
|
||||
everything that we have in flight
|
||||
- We can detect and fix CVEs early
|
||||
|
||||
## Goal: Take long-standing alpha commands out of alpha
|
||||
|
||||
Contributors: external contributions
|
||||
|
||||
Priority: Medium
|
||||
|
||||
Effort: Medium
|
||||
|
||||
Project board: https://github.com/orgs/kubernetes-sigs/projects/52
|
||||
|
||||
There are several commands in kustomize that have been alpha for a long time, including the cfg command group and
|
||||
localize. Moving them forward can indicate good health of a project and these commands are useful to many users.
|
||||
Some of these projects can be good starter issues for new contributors to have an easier onramp while others will
|
||||
require more effort and thought.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#
|
||||
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
|
||||
# INSTRUCTIONS AT https://kubernetes.io/security/
|
||||
|
||||
monopole
|
||||
Liujingfang1
|
||||
pwittrock
|
||||
eddiezane
|
||||
KnVerey
|
||||
natasha41575
|
||||
soltysh
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
include ../Makefile-modules.mk
|
||||
|
||||
test:
|
||||
go test -v -timeout 45m -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
|
||||
go test -v -timeout 45m -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.buildDate=2023-01-31T23:38:41Z -X sigs.k8s.io/kustomize/api/provenance.version=(test)"
|
||||
|
||||
build:
|
||||
go build -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222" ./...
|
||||
go build -ldflags "-X sigs.k8s.io/kustomize/api/provenance.buildDate=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")" ./...
|
||||
|
||||
generate: $(MYGOBIN)/k8scopy $(MYGOBIN)/stringer
|
||||
go generate ./...
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/api/filters/fieldspec"
|
||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
@@ -621,7 +622,7 @@ kind: Pod
|
||||
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := yaml.Unmarshal([]byte(tc.fieldSpec), &filter.FieldSpec)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
rw := &kio.ByteReadWriter{
|
||||
Reader: bytes.NewBufferString(tc.input),
|
||||
Writer: &bytes.Buffer{},
|
||||
@@ -635,7 +636,7 @@ kind: Pod
|
||||
Outputs: []kio.Writer{rw},
|
||||
}.Execute()
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, fieldPaths)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ package imagetag
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/image"
|
||||
"sigs.k8s.io/kustomize/api/internal/image"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
@@ -284,9 +284,9 @@ func (f Filter) roleRefFilter() sieveFunc {
|
||||
return previousIdSelectedByGvk(roleRefGvk)
|
||||
}
|
||||
|
||||
func prefixSuffixEquals(other resource.ResCtx) sieveFunc {
|
||||
func prefixSuffixEquals(other resource.ResCtx, allowEmpty bool) sieveFunc {
|
||||
return func(r *resource.Resource) bool {
|
||||
return r.PrefixesSuffixesEquals(other)
|
||||
return r.PrefixesSuffixesEquals(other, allowEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +325,10 @@ func (f Filter) selectReferral(
|
||||
if len(candidates) == 1 {
|
||||
return candidates[0], nil
|
||||
}
|
||||
candidates = doSieve(candidates, prefixSuffixEquals(f.Referrer))
|
||||
candidates = doSieve(candidates, prefixSuffixEquals(f.Referrer, true))
|
||||
if len(candidates) > 1 {
|
||||
candidates = doSieve(candidates, prefixSuffixEquals(f.Referrer, false))
|
||||
}
|
||||
if len(candidates) == 1 {
|
||||
return candidates[0], nil
|
||||
}
|
||||
|
||||
@@ -56,9 +56,11 @@ func (ns Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
|
||||
// Run runs the filter on a single node rather than a slice
|
||||
func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
||||
// Special handling for metadata.namespace -- :(
|
||||
// Special handling for metadata.namespace and metadata.name -- :(
|
||||
// never let SetEntry handle metadata.namespace--it will incorrectly include cluster-scoped resources
|
||||
ns.FsSlice = ns.removeMetaNamespaceFieldSpecs(ns.FsSlice)
|
||||
// only update metadata.name if api version is expected one--so-as it leaves other resources of kind namespace alone
|
||||
apiVersion := node.GetApiVersion()
|
||||
ns.FsSlice = ns.removeUnneededMetaFieldSpecs(apiVersion, ns.FsSlice)
|
||||
gvk := resid.GvkFromNode(node)
|
||||
if err := ns.metaNamespaceHack(node, gvk); err != nil {
|
||||
return nil, err
|
||||
@@ -186,12 +188,15 @@ func (ns Filter) removeRoleBindingSubjectFieldSpecs(fs types.FsSlice) types.FsSl
|
||||
return val
|
||||
}
|
||||
|
||||
func (ns Filter) removeMetaNamespaceFieldSpecs(fs types.FsSlice) types.FsSlice {
|
||||
func (ns Filter) removeUnneededMetaFieldSpecs(apiVersion string, fs types.FsSlice) types.FsSlice {
|
||||
var val types.FsSlice
|
||||
for i := range fs {
|
||||
if fs[i].Path == types.MetadataNamespacePath {
|
||||
continue
|
||||
}
|
||||
if apiVersion != types.MetadataNamespaceApiVersion && fs[i].Path == types.MetadataNamePath {
|
||||
continue
|
||||
}
|
||||
val = append(val, fs[i])
|
||||
}
|
||||
return val
|
||||
|
||||
@@ -6,7 +6,7 @@ package patchjson6902
|
||||
import (
|
||||
"strings"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
jsonpatch "gopkg.in/evanphx/json-patch.v4"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
k8syaml "sigs.k8s.io/yaml"
|
||||
|
||||
@@ -776,6 +776,133 @@ spec:
|
||||
autoscaling: true
|
||||
deepgram-api:
|
||||
some: value
|
||||
`,
|
||||
},
|
||||
|
||||
// Issue #4928
|
||||
"support numeric keys": {
|
||||
input: `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
"6443": "foobar"
|
||||
`,
|
||||
patch: yaml.MustParse(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
"6443": "barfoo"
|
||||
"9110": "foo-foo"
|
||||
`),
|
||||
expected: `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
"6443": "barfoo"
|
||||
"9110": "foo-foo"
|
||||
`,
|
||||
},
|
||||
|
||||
"honor different key style one": {
|
||||
input: `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
'6443': "foobar"
|
||||
`,
|
||||
patch: yaml.MustParse(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
"6443": "barfoo"
|
||||
9110: "foo-foo"
|
||||
`),
|
||||
expected: `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
'6443': "barfoo"
|
||||
9110: "foo-foo"
|
||||
`,
|
||||
},
|
||||
|
||||
"honor different key style two": {
|
||||
input: `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
"6443": "foobar"
|
||||
`,
|
||||
patch: yaml.MustParse(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
"6443": "barfoo"
|
||||
'9110': "foo-foo"
|
||||
`),
|
||||
expected: `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
"6443": "barfoo"
|
||||
'9110': "foo-foo"
|
||||
`,
|
||||
},
|
||||
|
||||
"different key types": {
|
||||
input: `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
"6443": "key-string-double-quoted"
|
||||
`,
|
||||
patch: yaml.MustParse(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
6443: "key-int"
|
||||
`),
|
||||
expected: `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blabla
|
||||
namespace: blabla-ns
|
||||
data:
|
||||
"6443": "key-int"
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -126,8 +126,8 @@ func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targetSelectors []
|
||||
}
|
||||
|
||||
// filter targets by matching resource IDs
|
||||
for i, id := range ids {
|
||||
if id.IsSelectedBy(selector.Select.ResId) && !rejectId(selector.Reject, &ids[i]) {
|
||||
for _, id := range ids {
|
||||
if id.IsSelectedBy(selector.Select.ResId) && !containsRejectId(selector.Reject, ids) {
|
||||
err := copyValueToTarget(possibleTarget, value, selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -168,10 +168,15 @@ func matchesAnnoAndLabelSelector(n *yaml.RNode, selector *types.Selector) (bool,
|
||||
return annoMatch && labelMatch, nil
|
||||
}
|
||||
|
||||
func rejectId(rejects []*types.Selector, id *resid.ResId) bool {
|
||||
func containsRejectId(rejects []*types.Selector, ids []resid.ResId) bool {
|
||||
for _, r := range rejects {
|
||||
if !r.ResId.IsEmpty() && id.IsSelectedBy(r.ResId) {
|
||||
return true
|
||||
if r.ResId.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
for _, id := range ids {
|
||||
if id.IsSelectedBy(r.ResId) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
37
api/go.mod
37
api/go.mod
@@ -1,36 +1,35 @@
|
||||
module sigs.k8s.io/kustomize/api
|
||||
|
||||
go 1.19
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible
|
||||
github.com/blang/semver/v4 v4.0.0
|
||||
github.com/go-errors/errors v1.4.2
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/imdario/mergo v0.3.6
|
||||
github.com/stretchr/testify v1.8.1
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.9
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.uber.org/goleak v1.3.0
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.0
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.1 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/go-cmp v0.5.5 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/xlab/treeprint v1.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
148
api/go.sum
148
api/go.sum
@@ -1,59 +1,41 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8=
|
||||
github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
|
||||
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
@@ -64,88 +46,54 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
|
||||
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
||||
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596 h1:8cNCQs+WqqnSpZ7y0LMQPKD+RZUHU17VqLPMW3qxnxc=
|
||||
k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0=
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk=
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.0 h1:G2bWs03V9Ur2PinHLzTUJ8Ded+30SzXZKiO92SRDs3c=
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.0/go.mod h1:6lxkYF1Cv9Ic8g/N7I86cvxNc5iinUo/P2vKsHNmpyE=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
. "sigs.k8s.io/kustomize/api/internal/accumulator"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||
|
||||
@@ -170,9 +170,10 @@ func (ra *ResAccumulator) FixBackReferences() (err error) {
|
||||
|
||||
// Intersection drops the resources which "other" does not have.
|
||||
func (ra *ResAccumulator) Intersection(other resmap.ResMap) error {
|
||||
otherIds := other.AllIds()
|
||||
for _, curId := range ra.resMap.AllIds() {
|
||||
toDelete := true
|
||||
for _, otherId := range other.AllIds() {
|
||||
for _, otherId := range otherIds {
|
||||
if otherId == curId {
|
||||
toDelete = false
|
||||
break
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on AnnotationsTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on ConfigMapGenerator; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on HashTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on HelmChartInflationGenerator; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
@@ -12,10 +12,12 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/imdario/mergo"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml/merge2"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
@@ -52,6 +54,15 @@ func (p *HelmChartInflationGeneratorPlugin) Config(
|
||||
if h.GeneralConfig().HelmConfig.Command == "" {
|
||||
return fmt.Errorf("must specify --helm-command")
|
||||
}
|
||||
|
||||
// CLI args takes precedence
|
||||
if h.GeneralConfig().HelmConfig.KubeVersion != "" {
|
||||
p.HelmChart.KubeVersion = h.GeneralConfig().HelmConfig.KubeVersion
|
||||
}
|
||||
if len(h.GeneralConfig().HelmConfig.ApiVersions) != 0 {
|
||||
p.HelmChart.ApiVersions = h.GeneralConfig().HelmConfig.ApiVersions
|
||||
}
|
||||
|
||||
p.h = h
|
||||
if err = yaml.Unmarshal(config, p); err != nil {
|
||||
return
|
||||
@@ -86,11 +97,19 @@ func (p *HelmChartInflationGeneratorPlugin) validateArgs() (err error) {
|
||||
p.ChartHome = types.HelmDefaultHome
|
||||
}
|
||||
|
||||
// The ValuesFile may be consulted by the plugin, so it must
|
||||
// The ValuesFile(s) may be consulted by the plugin, so it must
|
||||
// be under the loader root (unless root restrictions are
|
||||
// disabled).
|
||||
if p.ValuesFile == "" {
|
||||
p.ValuesFile = filepath.Join(p.ChartHome, p.Name, "values.yaml")
|
||||
p.ValuesFile = filepath.Join(p.absChartHome(), p.Name, "values.yaml")
|
||||
}
|
||||
for i, file := range p.AdditionalValuesFiles {
|
||||
// use Load() to enforce root restrictions
|
||||
if _, err := p.h.Loader().Load(file); err != nil {
|
||||
return errors.WrapPrefixf(err, "could not load additionalValuesFile")
|
||||
}
|
||||
// the additional values filepaths must be relative to the kust root
|
||||
p.AdditionalValuesFiles[i] = filepath.Join(p.h.Loader().Root(), file)
|
||||
}
|
||||
|
||||
if err = p.errIfIllegalValuesMerge(); err != nil {
|
||||
@@ -123,10 +142,17 @@ func (p *HelmChartInflationGeneratorPlugin) errIfIllegalValuesMerge() error {
|
||||
}
|
||||
|
||||
func (p *HelmChartInflationGeneratorPlugin) absChartHome() string {
|
||||
var chartHome string
|
||||
if filepath.IsAbs(p.ChartHome) {
|
||||
return p.ChartHome
|
||||
chartHome = p.ChartHome
|
||||
} else {
|
||||
chartHome = filepath.Join(p.h.Loader().Root(), p.ChartHome)
|
||||
}
|
||||
return filepath.Join(p.h.Loader().Root(), p.ChartHome)
|
||||
|
||||
if p.Version != "" && p.Repo != "" {
|
||||
return filepath.Join(chartHome, fmt.Sprintf("%s-%s", p.Name, p.Version))
|
||||
}
|
||||
return chartHome
|
||||
}
|
||||
|
||||
func (p *HelmChartInflationGeneratorPlugin) runHelmCommand(
|
||||
@@ -146,8 +172,8 @@ func (p *HelmChartInflationGeneratorPlugin) runHelmCommand(
|
||||
helm := p.h.GeneralConfig().HelmConfig.Command
|
||||
err = errors.WrapPrefixf(
|
||||
fmt.Errorf(
|
||||
"unable to run: '%s %s' with env=%s (is '%s' installed?)",
|
||||
helm, strings.Join(args, " "), env, helm),
|
||||
"unable to run: '%s %s' with env=%s (is '%s' installed?): %w",
|
||||
helm, strings.Join(args, " "), env, helm, err),
|
||||
stderr.String(),
|
||||
)
|
||||
}
|
||||
@@ -176,18 +202,33 @@ func (p *HelmChartInflationGeneratorPlugin) replaceValuesInline() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chValues := make(map[string]interface{})
|
||||
if err = yaml.Unmarshal(pValues, &chValues); err != nil {
|
||||
return err
|
||||
chValues, err := kyaml.Parse(string(pValues))
|
||||
if err != nil {
|
||||
return errors.WrapPrefixf(err, "could not parse values file into rnode")
|
||||
}
|
||||
inlineValues, err := kyaml.FromMap(p.ValuesInline)
|
||||
if err != nil {
|
||||
return errors.WrapPrefixf(err, "could not parse values inline into rnode")
|
||||
}
|
||||
var outValues *kyaml.RNode
|
||||
switch p.ValuesMerge {
|
||||
// Function `merge2.Merge` overrides values in dest with values from src.
|
||||
// To achieve override or merge behavior, we pass parameters in different order.
|
||||
// Object passed as dest will be modified, so we copy it just in case someone
|
||||
// decides to use it after this is called.
|
||||
case valuesMergeOptionOverride:
|
||||
err = mergo.Merge(
|
||||
&chValues, p.ValuesInline, mergo.WithOverride)
|
||||
outValues, err = merge2.Merge(inlineValues, chValues.Copy(), kyaml.MergeOptions{})
|
||||
case valuesMergeOptionMerge:
|
||||
err = mergo.Merge(&chValues, p.ValuesInline)
|
||||
outValues, err = merge2.Merge(chValues, inlineValues.Copy(), kyaml.MergeOptions{})
|
||||
}
|
||||
p.ValuesInline = chValues
|
||||
if err != nil {
|
||||
return errors.WrapPrefixf(err, "could not merge values")
|
||||
}
|
||||
mapValues, err := outValues.Map()
|
||||
if err != nil {
|
||||
return errors.WrapPrefixf(err, "could not parse merged values into map")
|
||||
}
|
||||
p.ValuesInline = mapValues
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -240,49 +281,31 @@ func (p *HelmChartInflationGeneratorPlugin) Generate() (rm resmap.ResMap, err er
|
||||
return nil, err
|
||||
}
|
||||
var stdout []byte
|
||||
stdout, err = p.runHelmCommand(p.templateCommand())
|
||||
stdout, err = p.runHelmCommand(p.AsHelmArgs(p.absChartHome()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rm, err = p.h.ResmapFactory().NewResMapFromBytes(stdout)
|
||||
if err == nil {
|
||||
rm, resMapErr := p.h.ResmapFactory().NewResMapFromBytes(stdout)
|
||||
if resMapErr == nil {
|
||||
return rm, nil
|
||||
}
|
||||
// try to remove the contents before first "---" because
|
||||
// helm may produce messages to stdout before it
|
||||
stdoutStr := string(stdout)
|
||||
if idx := strings.Index(stdoutStr, "\n---\n"); idx != -1 {
|
||||
return p.h.ResmapFactory().NewResMapFromBytes([]byte(stdoutStr[idx:]))
|
||||
r := &kio.ByteReader{Reader: bytes.NewBufferString(string(stdout)), OmitReaderAnnotations: true}
|
||||
nodes, err := r.Read()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading helm output: %w", err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string {
|
||||
args := []string{"template"}
|
||||
if p.ReleaseName != "" {
|
||||
args = append(args, p.ReleaseName)
|
||||
if len(nodes) != 0 {
|
||||
rm, err = p.h.ResmapFactory().NewResMapFromRNodeSlice(nodes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse rnode slice into resource map: %w", err)
|
||||
}
|
||||
return rm, nil
|
||||
}
|
||||
if p.Namespace != "" {
|
||||
args = append(args, "--namespace", p.Namespace)
|
||||
}
|
||||
args = append(args, filepath.Join(p.absChartHome(), p.Name))
|
||||
if p.ValuesFile != "" {
|
||||
args = append(args, "--values", p.ValuesFile)
|
||||
}
|
||||
if p.ReleaseName == "" {
|
||||
// AFAICT, this doesn't work as intended due to a bug in helm.
|
||||
// See https://github.com/helm/helm/issues/6019
|
||||
// I've tried placing the flag before and after the name argument.
|
||||
args = append(args, "--generate-name")
|
||||
}
|
||||
if p.IncludeCRDs {
|
||||
args = append(args, "--include-crds")
|
||||
}
|
||||
if p.SkipHooks {
|
||||
args = append(args, "--no-hooks")
|
||||
}
|
||||
return args
|
||||
return nil, fmt.Errorf("could not parse bytes into resource map: %w", resMapErr)
|
||||
}
|
||||
|
||||
func (p *HelmChartInflationGeneratorPlugin) pullCommand() []string {
|
||||
@@ -290,8 +313,18 @@ func (p *HelmChartInflationGeneratorPlugin) pullCommand() []string {
|
||||
"pull",
|
||||
"--untar",
|
||||
"--untardir", p.absChartHome(),
|
||||
"--repo", p.Repo,
|
||||
p.Name}
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(p.Repo, "oci://"):
|
||||
args = append(args, strings.TrimSuffix(p.Repo, "/")+"/"+p.Name)
|
||||
case p.Repo != "":
|
||||
args = append(args, "--repo", p.Repo)
|
||||
fallthrough
|
||||
default:
|
||||
args = append(args, p.Name)
|
||||
}
|
||||
|
||||
if p.Version != "" {
|
||||
args = append(args, "--version", p.Version)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on IAMPolicyGenerator; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on ImageTagTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on LabelTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on NamespaceTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Code generated by pluginator on PatchJson6902Transformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
jsonpatch "gopkg.in/evanphx/json-patch.v4"
|
||||
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on PatchStrategicMergeTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on PatchTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
@@ -7,104 +7,123 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
jsonpatch "gopkg.in/evanphx/json-patch.v4"
|
||||
"sigs.k8s.io/kustomize/api/filters/patchjson6902"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
type PatchTransformerPlugin struct {
|
||||
loadedPatch *resource.Resource
|
||||
decodedPatch jsonpatch.Patch
|
||||
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
|
||||
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
|
||||
Options map[string]bool `json:"options,omitempty" yaml:"options,omitempty"`
|
||||
smPatches []*resource.Resource // strategic-merge patches
|
||||
jsonPatches jsonpatch.Patch // json6902 patch
|
||||
// patchText is pure patch text created by Path or Patch
|
||||
patchText string
|
||||
// patchSource is patch source message
|
||||
patchSource string
|
||||
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||
Patch string `json:"patch,omitempty" yaml:"patch,omitempty"`
|
||||
Target *types.Selector `json:"target,omitempty" yaml:"target,omitempty"`
|
||||
Options map[string]bool `json:"options,omitempty" yaml:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (p *PatchTransformerPlugin) Config(
|
||||
h *resmap.PluginHelpers, c []byte) error {
|
||||
err := yaml.Unmarshal(c, p)
|
||||
if err != nil {
|
||||
func (p *PatchTransformerPlugin) Config(h *resmap.PluginHelpers, c []byte) error {
|
||||
if err := yaml.Unmarshal(c, p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Patch = strings.TrimSpace(p.Patch)
|
||||
if p.Patch == "" && p.Path == "" {
|
||||
return fmt.Errorf(
|
||||
"must specify one of patch and path in\n%s", string(c))
|
||||
}
|
||||
if p.Patch != "" && p.Path != "" {
|
||||
return fmt.Errorf(
|
||||
"patch and path can't be set at the same time\n%s", string(c))
|
||||
}
|
||||
if p.Path != "" {
|
||||
loaded, loadErr := h.Loader().Load(p.Path)
|
||||
if loadErr != nil {
|
||||
return loadErr
|
||||
switch {
|
||||
case p.Patch == "" && p.Path == "":
|
||||
return fmt.Errorf("must specify one of patch and path in\n%s", string(c))
|
||||
case p.Patch != "" && p.Path != "":
|
||||
return fmt.Errorf("patch and path can't be set at the same time\n%s", string(c))
|
||||
case p.Patch != "":
|
||||
p.patchText = p.Patch
|
||||
p.patchSource = fmt.Sprintf("[patch: %q]", p.patchText)
|
||||
case p.Path != "":
|
||||
loaded, err := h.Loader().Load(p.Path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get the patch file from path(%s): %w", p.Path, err)
|
||||
}
|
||||
p.Patch = string(loaded)
|
||||
p.patchText = string(loaded)
|
||||
p.patchSource = fmt.Sprintf("[path: %q]", p.Path)
|
||||
}
|
||||
|
||||
patchSM, errSM := h.ResmapFactory().RF().FromBytes([]byte(p.Patch))
|
||||
patchJson, errJson := jsonPatchFromBytes([]byte(p.Patch))
|
||||
patchesSM, errSM := h.ResmapFactory().RF().SliceFromBytes([]byte(p.patchText))
|
||||
patchesJson, errJson := jsonPatchFromBytes([]byte(p.patchText))
|
||||
|
||||
if (errSM == nil && errJson == nil) ||
|
||||
(patchSM != nil && patchJson != nil) {
|
||||
(patchesSM != nil && patchesJson != nil) {
|
||||
return fmt.Errorf(
|
||||
"illegally qualifies as both an SM and JSON patch: [%v]",
|
||||
p.Patch)
|
||||
"illegally qualifies as both an SM and JSON patch: %s",
|
||||
p.patchSource)
|
||||
}
|
||||
if errSM != nil && errJson != nil {
|
||||
return fmt.Errorf(
|
||||
"unable to parse SM or JSON patch from [%v]", p.Patch)
|
||||
"unable to parse SM or JSON patch from %s", p.patchSource)
|
||||
}
|
||||
if errSM == nil {
|
||||
p.loadedPatch = patchSM
|
||||
if p.Options["allowNameChange"] {
|
||||
p.loadedPatch.AllowNameChange()
|
||||
}
|
||||
if p.Options["allowKindChange"] {
|
||||
p.loadedPatch.AllowKindChange()
|
||||
p.smPatches = patchesSM
|
||||
for _, loadedPatch := range p.smPatches {
|
||||
if p.Options["allowNameChange"] {
|
||||
loadedPatch.AllowNameChange()
|
||||
}
|
||||
if p.Options["allowKindChange"] {
|
||||
loadedPatch.AllowKindChange()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p.decodedPatch = patchJson
|
||||
p.jsonPatches = patchesJson
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PatchTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||
if p.loadedPatch == nil {
|
||||
return p.transformJson6902(m, p.decodedPatch)
|
||||
if p.smPatches != nil {
|
||||
return p.transformStrategicMerge(m)
|
||||
}
|
||||
// The patch was a strategic merge patch
|
||||
return p.transformStrategicMerge(m, p.loadedPatch)
|
||||
return p.transformJson6902(m)
|
||||
}
|
||||
|
||||
// transformStrategicMerge applies the provided strategic merge patch
|
||||
// to all the resources in the ResMap that match either the Target or
|
||||
// the identifier of the patch.
|
||||
func (p *PatchTransformerPlugin) transformStrategicMerge(m resmap.ResMap, patch *resource.Resource) error {
|
||||
if p.Target == nil {
|
||||
// transformStrategicMerge applies each loaded strategic merge patch
|
||||
// to the resource in the ResMap that matches the identifier of the patch.
|
||||
// If only one patch is specified, the Target can be used instead.
|
||||
func (p *PatchTransformerPlugin) transformStrategicMerge(m resmap.ResMap) error {
|
||||
if p.Target != nil {
|
||||
if len(p.smPatches) > 1 {
|
||||
// detail: https://github.com/kubernetes-sigs/kustomize/issues/5049#issuecomment-1440604403
|
||||
return fmt.Errorf("Multiple Strategic-Merge Patches in one `patches` entry is not allowed to set `patches.target` field: %s", p.patchSource)
|
||||
}
|
||||
|
||||
// single patch
|
||||
patch := p.smPatches[0]
|
||||
selected, err := m.Select(*p.Target)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to find patch target %q in `resources`: %w", p.Target, err)
|
||||
}
|
||||
return errors.Wrap(m.ApplySmPatch(resource.MakeIdSet(selected), patch))
|
||||
}
|
||||
|
||||
for _, patch := range p.smPatches {
|
||||
target, err := m.GetById(patch.OrgId())
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("no resource matches strategic merge patch %q: %w", patch.OrgId(), err)
|
||||
}
|
||||
if err := target.ApplySmPatch(patch); err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
return target.ApplySmPatch(patch)
|
||||
}
|
||||
selected, err := m.Select(*p.Target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.ApplySmPatch(resource.MakeIdSet(selected), patch)
|
||||
return nil
|
||||
}
|
||||
|
||||
// transformJson6902 applies the provided json6902 patch
|
||||
// to all the resources in the ResMap that match the Target.
|
||||
func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpatch.Patch) error {
|
||||
// transformJson6902 applies json6902 Patch to all the resources in the ResMap that match Target.
|
||||
func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap) error {
|
||||
if p.Target == nil {
|
||||
return fmt.Errorf("must specify a target for patch %s", p.Patch)
|
||||
return fmt.Errorf("must specify a target for JSON patch %s", p.patchSource)
|
||||
}
|
||||
resources, err := m.Select(*p.Target)
|
||||
if err != nil {
|
||||
@@ -114,7 +133,7 @@ func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpa
|
||||
res.StorePreviousId()
|
||||
internalAnnotations := kioutil.GetInternalAnnotations(&res.RNode)
|
||||
err = res.ApplyFilter(patchjson6902.Filter{
|
||||
Patch: p.Patch,
|
||||
Patch: p.patchText,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -129,16 +148,17 @@ func (p *PatchTransformerPlugin) transformJson6902(m resmap.ResMap, patch jsonpa
|
||||
return nil
|
||||
}
|
||||
|
||||
// jsonPatchFromBytes loads a Json 6902 patch from
|
||||
// a bytes input
|
||||
func jsonPatchFromBytes(
|
||||
in []byte) (jsonpatch.Patch, error) {
|
||||
// jsonPatchFromBytes loads a Json 6902 patch from a bytes input
|
||||
func jsonPatchFromBytes(in []byte) (jsonpatch.Patch, error) {
|
||||
ops := string(in)
|
||||
if ops == "" {
|
||||
return nil, fmt.Errorf("empty json patch operations")
|
||||
}
|
||||
|
||||
if ops[0] != '[' {
|
||||
// TODO(5049):
|
||||
// In the case of multiple yaml documents, return error instead of ignoring all but first.
|
||||
// Details: https://github.com/kubernetes-sigs/kustomize/pull/5194#discussion_r1256686728
|
||||
jsonOps, err := yaml.YAMLToJSON(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on PrefixTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on ReplacementTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on ReplicaCountTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on SecretGenerator; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on SortOrderTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on SuffixTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by pluginator on ValueAddTransformer; DO NOT EDIT.
|
||||
// pluginator {unknown 1970-01-01T00:00:00Z }
|
||||
// pluginator {(devel) unknown }
|
||||
|
||||
package builtins
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
. "sigs.k8s.io/kustomize/api/internal/generators"
|
||||
"sigs.k8s.io/kustomize/api/kv"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
. "sigs.k8s.io/kustomize/api/internal/generators"
|
||||
"sigs.k8s.io/kustomize/api/kv"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
|
||||
@@ -22,10 +22,16 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
||||
if err = r.run("init"); err != nil {
|
||||
return err
|
||||
}
|
||||
// git relative submodule need origin, see https://github.com/kubernetes-sigs/kustomize/issues/5131
|
||||
if err = r.run("remote", "add", "origin", repoSpec.CloneSpec()); err != nil {
|
||||
return err
|
||||
}
|
||||
ref := "HEAD"
|
||||
if repoSpec.Ref != "" {
|
||||
ref = repoSpec.Ref
|
||||
}
|
||||
// we use repoSpec.CloneSpec() instead of origin because on error,
|
||||
// the prior prints the actual repo url for the user.
|
||||
if err = r.run("fetch", "--depth=1", repoSpec.CloneSpec(), ref); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -370,8 +370,9 @@ func trimPrefixIgnoreCase(s, prefix string) (string, bool) {
|
||||
func findPathSeparator(hostPath string, acceptSCP bool) int {
|
||||
sepIndex := strings.Index(hostPath, pathSeparator)
|
||||
if acceptSCP {
|
||||
colonIndex := strings.Index(hostPath, ":")
|
||||
// The colon acts as a delimiter in scp-style ssh URLs only if not prefixed by '/'.
|
||||
if colonIndex := strings.Index(hostPath, ":"); colonIndex > 0 && colonIndex < sepIndex {
|
||||
if sepIndex == -1 || (colonIndex > 0 && colonIndex < sepIndex) {
|
||||
sepIndex = colonIndex
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,6 +659,26 @@ func TestNewRepoSpecFromUrl_Smoke(t *testing.T) {
|
||||
RepoPath: "kubernetes-sigs/kustomize",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "scp format gist url",
|
||||
input: "git@gist.github.com:bc7947cb727d7f9217e7862d961a1ffd.git",
|
||||
cloneSpec: "git@gist.github.com:bc7947cb727d7f9217e7862d961a1ffd.git",
|
||||
absPath: notCloned.String(),
|
||||
repoSpec: RepoSpec{
|
||||
Host: "git@gist.github.com:",
|
||||
RepoPath: "bc7947cb727d7f9217e7862d961a1ffd.git",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "https gist url",
|
||||
input: "https://gist.github.com/bc7947cb727d7f9217e7862d961a1ffd.git",
|
||||
cloneSpec: "https://gist.github.com/bc7947cb727d7f9217e7862d961a1ffd.git",
|
||||
absPath: notCloned.String(),
|
||||
repoSpec: RepoSpec{
|
||||
Host: "https://gist.github.com/",
|
||||
RepoPath: "bc7947cb727d7f9217e7862d961a1ffd.git",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// Copyright 2020 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package image
|
||||
package image_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"sigs.k8s.io/kustomize/api/internal/image"
|
||||
)
|
||||
|
||||
func TestIsImageMatched(t *testing.T) {
|
||||
@@ -50,7 +51,7 @@ func TestIsImageMatched(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
assert.Equal(t, tc.isMatched, IsImageMatched(tc.value, tc.name))
|
||||
assert.Equal(t, tc.isMatched, image.IsImageMatched(tc.value, tc.name))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -116,7 +117,7 @@ func TestSplit(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
name, tag, digest := Split(tc.value)
|
||||
name, tag, digest := image.Split(tc.value)
|
||||
assert.Equal(t, tc.name, name)
|
||||
assert.Equal(t, tc.tag, tag)
|
||||
assert.Equal(t, tc.digest, digest)
|
||||
@@ -25,7 +25,7 @@ func IsRemoteFile(path string) bool {
|
||||
return err == nil && (u.Scheme == "http" || u.Scheme == "https")
|
||||
}
|
||||
|
||||
// fileLoader is a kustomization's interface to files.
|
||||
// FileLoader is a kustomization's interface to files.
|
||||
//
|
||||
// The directory in which a kustomization file sits
|
||||
// is referred to below as the kustomization's _root_.
|
||||
@@ -38,49 +38,48 @@ func IsRemoteFile(path string) bool {
|
||||
//
|
||||
// * supplemental data paths
|
||||
//
|
||||
// `Load` is used to visit these paths.
|
||||
// `Load` is used to visit these paths.
|
||||
//
|
||||
// These paths refer to resources, patches,
|
||||
// data for ConfigMaps and Secrets, etc.
|
||||
// These paths refer to resources, patches,
|
||||
// data for ConfigMaps and Secrets, etc.
|
||||
//
|
||||
// The loadRestrictor may disallow certain paths
|
||||
// or classes of paths.
|
||||
// The loadRestrictor may disallow certain paths
|
||||
// or classes of paths.
|
||||
//
|
||||
// * bases (other kustomizations)
|
||||
//
|
||||
// `New` is used to load bases.
|
||||
// `New` is used to load bases.
|
||||
//
|
||||
// A base can be either a remote git repo URL, or
|
||||
// a directory specified relative to the current
|
||||
// root. In the former case, the repo is locally
|
||||
// cloned, and the new loader is rooted on a path
|
||||
// in that clone.
|
||||
// A base can be either a remote git repo URL, or
|
||||
// a directory specified relative to the current
|
||||
// root. In the former case, the repo is locally
|
||||
// cloned, and the new loader is rooted on a path
|
||||
// in that clone.
|
||||
//
|
||||
// As loaders create new loaders, a root history
|
||||
// is established, and used to disallow:
|
||||
// As loaders create new loaders, a root history
|
||||
// is established, and used to disallow:
|
||||
//
|
||||
// - A base that is a repository that, in turn,
|
||||
// specifies a base repository seen previously
|
||||
// in the loading stack (a cycle).
|
||||
// - A base that is a repository that, in turn,
|
||||
// specifies a base repository seen previously
|
||||
// in the loading stack (a cycle).
|
||||
//
|
||||
// - An overlay depending on a base positioned at
|
||||
// or above it. I.e. '../foo' is OK, but '.',
|
||||
// '..', '../..', etc. are disallowed. Allowing
|
||||
// such a base has no advantages and encourages
|
||||
// cycles, particularly if some future change
|
||||
// were to introduce globbing to file
|
||||
// specifications in the kustomization file.
|
||||
// - An overlay depending on a base positioned at
|
||||
// or above it. I.e. '../foo' is OK, but '.',
|
||||
// '..', '../..', etc. are disallowed. Allowing
|
||||
// such a base has no advantages and encourages
|
||||
// cycles, particularly if some future change
|
||||
// were to introduce globbing to file
|
||||
// specifications in the kustomization file.
|
||||
//
|
||||
// These restrictions assure that kustomizations
|
||||
// are self-contained and relocatable, and impose
|
||||
// some safety when relying on remote kustomizations,
|
||||
// e.g. a remotely loaded ConfigMap generator specified
|
||||
// to read from /etc/passwd will fail.
|
||||
//
|
||||
type fileLoader struct {
|
||||
type FileLoader struct {
|
||||
// Loader that spawned this loader.
|
||||
// Used to avoid cycles.
|
||||
referrer *fileLoader
|
||||
referrer *FileLoader
|
||||
|
||||
// An absolute, cleaned path to a directory.
|
||||
// The Load function will read non-absolute
|
||||
@@ -107,23 +106,9 @@ type fileLoader struct {
|
||||
cleaner func() error
|
||||
}
|
||||
|
||||
// NewFileLoaderAtCwd returns a loader that loads from PWD.
|
||||
// A convenience for kustomize edit commands.
|
||||
func NewFileLoaderAtCwd(fSys filesys.FileSystem) *fileLoader {
|
||||
return newLoaderOrDie(
|
||||
RestrictionRootOnly, fSys, filesys.SelfDir)
|
||||
}
|
||||
|
||||
// NewFileLoaderAtRoot returns a loader that loads from "/".
|
||||
// A convenience for tests.
|
||||
func NewFileLoaderAtRoot(fSys filesys.FileSystem) *fileLoader {
|
||||
return newLoaderOrDie(
|
||||
RestrictionRootOnly, fSys, filesys.Separator)
|
||||
}
|
||||
|
||||
// Repo returns the absolute path to the repo that contains Root if this fileLoader was created from a url
|
||||
// or the empty string otherwise.
|
||||
func (fl *fileLoader) Repo() string {
|
||||
func (fl *FileLoader) Repo() string {
|
||||
if fl.repoSpec != nil {
|
||||
return fl.repoSpec.Dir.String()
|
||||
}
|
||||
@@ -132,13 +117,13 @@ func (fl *fileLoader) Repo() string {
|
||||
|
||||
// Root returns the absolute path that is prepended to any
|
||||
// relative paths used in Load.
|
||||
func (fl *fileLoader) Root() string {
|
||||
func (fl *FileLoader) Root() string {
|
||||
return fl.root.String()
|
||||
}
|
||||
|
||||
func newLoaderOrDie(
|
||||
func NewLoaderOrDie(
|
||||
lr LoadRestrictorFunc,
|
||||
fSys filesys.FileSystem, path string) *fileLoader {
|
||||
fSys filesys.FileSystem, path string) *FileLoader {
|
||||
root, err := filesys.ConfirmDir(fSys, path)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to make loader at '%s'; %v", path, err)
|
||||
@@ -147,12 +132,12 @@ func newLoaderOrDie(
|
||||
lr, root, fSys, nil, git.ClonerUsingGitExec)
|
||||
}
|
||||
|
||||
// newLoaderAtConfirmedDir returns a new fileLoader with given root.
|
||||
// newLoaderAtConfirmedDir returns a new FileLoader with given root.
|
||||
func newLoaderAtConfirmedDir(
|
||||
lr LoadRestrictorFunc,
|
||||
root filesys.ConfirmedDir, fSys filesys.FileSystem,
|
||||
referrer *fileLoader, cloner git.Cloner) *fileLoader {
|
||||
return &fileLoader{
|
||||
referrer *FileLoader, cloner git.Cloner) *FileLoader {
|
||||
return &FileLoader{
|
||||
loadRestrictor: lr,
|
||||
root: root,
|
||||
referrer: referrer,
|
||||
@@ -164,7 +149,7 @@ func newLoaderAtConfirmedDir(
|
||||
|
||||
// New returns a new Loader, rooted relative to current loader,
|
||||
// or rooted in a temp directory holding a git repo clone.
|
||||
func (fl *fileLoader) New(path string) (ifc.Loader, error) {
|
||||
func (fl *FileLoader) New(path string) (ifc.Loader, error) {
|
||||
if path == "" {
|
||||
return nil, errors.Errorf("new root cannot be empty")
|
||||
}
|
||||
@@ -200,7 +185,7 @@ func (fl *fileLoader) New(path string) (ifc.Loader, error) {
|
||||
// directory holding a cloned git repo.
|
||||
func newLoaderAtGitClone(
|
||||
repoSpec *git.RepoSpec, fSys filesys.FileSystem,
|
||||
referrer *fileLoader, cloner git.Cloner) (ifc.Loader, error) {
|
||||
referrer *FileLoader, cloner git.Cloner) (ifc.Loader, error) {
|
||||
cleaner := repoSpec.Cleaner(fSys)
|
||||
err := cloner(repoSpec)
|
||||
if err != nil {
|
||||
@@ -229,7 +214,7 @@ func newLoaderAtGitClone(
|
||||
return nil, fmt.Errorf("%q refers to directory outside of repo %q", repoSpec.AbsPath(),
|
||||
repoSpec.CloneDir())
|
||||
}
|
||||
return &fileLoader{
|
||||
return &FileLoader{
|
||||
// Clones never allowed to escape root.
|
||||
loadRestrictor: RestrictionRootOnly,
|
||||
root: root,
|
||||
@@ -241,7 +226,7 @@ func newLoaderAtGitClone(
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (fl *fileLoader) errIfGitContainmentViolation(
|
||||
func (fl *FileLoader) errIfGitContainmentViolation(
|
||||
base filesys.ConfirmedDir) error {
|
||||
containingRepo := fl.containingRepo()
|
||||
if containingRepo == nil {
|
||||
@@ -259,7 +244,7 @@ func (fl *fileLoader) errIfGitContainmentViolation(
|
||||
|
||||
// Looks back through referrers for a git repo, returning nil
|
||||
// if none found.
|
||||
func (fl *fileLoader) containingRepo() *git.RepoSpec {
|
||||
func (fl *FileLoader) containingRepo() *git.RepoSpec {
|
||||
if fl.repoSpec != nil {
|
||||
return fl.repoSpec
|
||||
}
|
||||
@@ -271,7 +256,7 @@ func (fl *fileLoader) containingRepo() *git.RepoSpec {
|
||||
|
||||
// errIfArgEqualOrHigher tests whether the argument,
|
||||
// is equal to or above the root of any ancestor.
|
||||
func (fl *fileLoader) errIfArgEqualOrHigher(
|
||||
func (fl *FileLoader) errIfArgEqualOrHigher(
|
||||
candidateRoot filesys.ConfirmedDir) error {
|
||||
if fl.root.HasPrefix(candidateRoot) {
|
||||
return fmt.Errorf(
|
||||
@@ -288,7 +273,7 @@ func (fl *fileLoader) errIfArgEqualOrHigher(
|
||||
// I.e. Allow a distinction between git URI with
|
||||
// path foo and tag bar and a git URI with the same
|
||||
// path but a different tag?
|
||||
func (fl *fileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error {
|
||||
func (fl *FileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error {
|
||||
// TODO(monopole): Use parsed data instead of Raw().
|
||||
if fl.repoSpec != nil &&
|
||||
strings.HasPrefix(fl.repoSpec.Raw(), newRepoSpec.Raw()) {
|
||||
@@ -305,7 +290,7 @@ func (fl *fileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error {
|
||||
// Load returns the content of file at the given path,
|
||||
// else an error. Relative paths are taken relative
|
||||
// to the root.
|
||||
func (fl *fileLoader) Load(path string) ([]byte, error) {
|
||||
func (fl *FileLoader) Load(path string) ([]byte, error) {
|
||||
if IsRemoteFile(path) {
|
||||
return fl.httpClientGetContent(path)
|
||||
}
|
||||
@@ -319,7 +304,7 @@ func (fl *fileLoader) Load(path string) ([]byte, error) {
|
||||
return fl.fSys.ReadFile(path)
|
||||
}
|
||||
|
||||
func (fl *fileLoader) httpClientGetContent(path string) ([]byte, error) {
|
||||
func (fl *FileLoader) httpClientGetContent(path string) ([]byte, error) {
|
||||
var hc *http.Client
|
||||
if fl.http != nil {
|
||||
hc = fl.http
|
||||
@@ -344,6 +329,6 @@ func (fl *fileLoader) httpClientGetContent(path string) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Cleanup runs the cleaner.
|
||||
func (fl *fileLoader) Cleanup() error {
|
||||
func (fl *FileLoader) Cleanup() error {
|
||||
return fl.cleaner()
|
||||
}
|
||||
@@ -31,6 +31,11 @@ func TestIsRemoteFile(t *testing.T) {
|
||||
"https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/helloWorld/configMap.yaml",
|
||||
true,
|
||||
},
|
||||
"malformed https": {
|
||||
// TODO(annasong): Maybe we want to fix this. Needs more research.
|
||||
"https:/raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/helloWorld/configMap.yaml",
|
||||
true,
|
||||
},
|
||||
"https dir": {
|
||||
"https://github.com/kubernetes-sigs/kustomize//examples/helloWorld/",
|
||||
true,
|
||||
@@ -88,8 +93,9 @@ func MakeFakeFs(td []testData) filesys.FileSystem {
|
||||
return fSys
|
||||
}
|
||||
|
||||
func makeLoader() *fileLoader {
|
||||
return NewFileLoaderAtRoot(MakeFakeFs(testCases))
|
||||
func makeLoader() *FileLoader {
|
||||
return NewLoaderOrDie(
|
||||
RestrictionRootOnly, MakeFakeFs(testCases), filesys.Separator)
|
||||
}
|
||||
|
||||
func TestLoaderLoad(t *testing.T) {
|
||||
@@ -196,13 +202,52 @@ func TestLoaderBadRelative(t *testing.T) {
|
||||
require.Error(err)
|
||||
}
|
||||
|
||||
func TestLoaderMisc(t *testing.T) {
|
||||
l := makeLoader()
|
||||
_, err := l.New("")
|
||||
func TestNewEmptyLoader(t *testing.T) {
|
||||
_, err := makeLoader().New("")
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
_, err = l.New("https://google.com/project")
|
||||
require.Error(t, err)
|
||||
func TestNewRemoteLoaderDoesNotExist(t *testing.T) {
|
||||
_, err := makeLoader().New("https://example.com/org/repo")
|
||||
require.ErrorContains(t, err, "fetch")
|
||||
}
|
||||
|
||||
func TestLoaderLocalScheme(t *testing.T) {
|
||||
// It is unlikely but possible for a reference with a url scheme to
|
||||
// actually refer to a local file or directory.
|
||||
t.Run("file", func(t *testing.T) {
|
||||
fSys, dir := setupOnDisk(t)
|
||||
parts := []string{
|
||||
"ssh:",
|
||||
"resource.yaml",
|
||||
}
|
||||
require.NoError(t, fSys.Mkdir(dir.Join(parts[0])))
|
||||
const content = "resource config"
|
||||
require.NoError(t, fSys.WriteFile(
|
||||
dir.Join(filepath.Join(parts...)),
|
||||
[]byte(content),
|
||||
))
|
||||
actualContent, err := NewLoaderOrDie(RestrictionRootOnly,
|
||||
fSys,
|
||||
dir.String(),
|
||||
).Load(strings.Join(parts, "//"))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, content, string(actualContent))
|
||||
})
|
||||
t.Run("directory", func(t *testing.T) {
|
||||
fSys, dir := setupOnDisk(t)
|
||||
parts := []string{
|
||||
"https:",
|
||||
"root",
|
||||
}
|
||||
require.NoError(t, fSys.MkdirAll(dir.Join(filepath.Join(parts...))))
|
||||
ldr, err := NewLoaderOrDie(RestrictionRootOnly,
|
||||
fSys,
|
||||
dir.String(),
|
||||
).New(strings.Join(parts, "//"))
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, ldr.Repo())
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -212,17 +257,17 @@ const (
|
||||
|
||||
// Create a structure like this
|
||||
//
|
||||
// /tmp/kustomize-test-random
|
||||
// ├── base
|
||||
// │ ├── okayData
|
||||
// │ ├── symLinkToOkayData -> okayData
|
||||
// │ └── symLinkToExteriorData -> ../exteriorData
|
||||
// └── exteriorData
|
||||
//
|
||||
// /tmp/kustomize-test-random
|
||||
// ├── base
|
||||
// │ ├── okayData
|
||||
// │ ├── symLinkToOkayData -> okayData
|
||||
// │ └── symLinkToExteriorData -> ../exteriorData
|
||||
// └── exteriorData
|
||||
func commonSetupForLoaderRestrictionTest(t *testing.T) (string, filesys.FileSystem) {
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
fSys := filesys.MakeFsOnDisk()
|
||||
fSys, tmpDir := setupOnDisk(t)
|
||||
dir := tmpDir.String()
|
||||
|
||||
fSys.Mkdir(filepath.Join(dir, "base"))
|
||||
|
||||
fSys.WriteFile(
|
||||
@@ -278,7 +323,7 @@ func TestRestrictionRootOnlyInRealLoader(t *testing.T) {
|
||||
|
||||
var l ifc.Loader
|
||||
|
||||
l = newLoaderOrDie(RestrictionRootOnly, fSys, dir)
|
||||
l = NewLoaderOrDie(RestrictionRootOnly, fSys, dir)
|
||||
|
||||
l = doSanityChecksAndDropIntoBase(t, l)
|
||||
|
||||
@@ -299,7 +344,7 @@ func TestRestrictionNoneInRealLoader(t *testing.T) {
|
||||
|
||||
var l ifc.Loader
|
||||
|
||||
l = newLoaderOrDie(RestrictionNone, fSys, dir)
|
||||
l = NewLoaderOrDie(RestrictionNone, fSys, dir)
|
||||
|
||||
l = doSanityChecksAndDropIntoBase(t, l)
|
||||
|
||||
@@ -398,7 +443,7 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) {
|
||||
|
||||
// Establish that a local overlay can navigate
|
||||
// to the local bases.
|
||||
l1 = newLoaderOrDie(
|
||||
l1 = NewLoaderOrDie(
|
||||
RestrictionRootOnly, fSys, cloneRoot+"/foo/overlay")
|
||||
require.Equal(cloneRoot+"/foo/overlay", l1.Root())
|
||||
|
||||
@@ -446,12 +491,8 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoaderDisallowsRemoteBaseExitRepo(t *testing.T) {
|
||||
fSys := filesys.MakeFsOnDisk()
|
||||
dir, err := filesys.NewTmpConfirmedDir()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
_ = fSys.RemoveAll(dir.String())
|
||||
})
|
||||
fSys, dir := setupOnDisk(t)
|
||||
|
||||
repo := dir.Join("repo")
|
||||
require.NoError(t, fSys.Mkdir(repo))
|
||||
|
||||
@@ -560,7 +601,8 @@ func TestLoaderHTTP(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
l1 := NewFileLoaderAtRoot(MakeFakeFs(testCasesFile))
|
||||
l1 := NewLoaderOrDie(
|
||||
RestrictionRootOnly, MakeFakeFs(testCasesFile), filesys.Separator)
|
||||
require.Equal("/", l1.Root())
|
||||
|
||||
for _, x := range testCasesFile {
|
||||
@@ -618,3 +660,19 @@ func TestLoaderHTTP(t *testing.T) {
|
||||
require.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// setupOnDisk sets up a file system on disk and directory that is cleaned after
|
||||
// test completion.
|
||||
// TODO(annasong): Move all loader tests that require real file system into
|
||||
// api/krusty.
|
||||
func setupOnDisk(t *testing.T) (filesys.FileSystem, filesys.ConfirmedDir) {
|
||||
t.Helper()
|
||||
|
||||
fSys := filesys.MakeFsOnDisk()
|
||||
dir, err := filesys.NewTmpConfirmedDir()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
_ = fSys.RemoveAll(dir.String())
|
||||
})
|
||||
return fSys, dir
|
||||
}
|
||||
@@ -48,6 +48,14 @@ func (lbp *localizeBuiltinPlugins) Filter(plugins []*yaml.RNode) ([]*yaml.RNode,
|
||||
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.SecretGenerator.String()},
|
||||
Path: "envs",
|
||||
},
|
||||
types.FieldSpec{
|
||||
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.HelmChartInflationGenerator.String()},
|
||||
Path: "valuesFile",
|
||||
},
|
||||
types.FieldSpec{
|
||||
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.HelmChartInflationGenerator.String()},
|
||||
Path: "additionalValuesFiles",
|
||||
},
|
||||
types.FieldSpec{
|
||||
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.PatchTransformer.String()},
|
||||
Path: "path",
|
||||
@@ -82,6 +90,24 @@ func (lbp *localizeBuiltinPlugins) Filter(plugins []*yaml.RNode) ([]*yaml.RNode,
|
||||
return lbp.localizeAll(node)
|
||||
},
|
||||
},
|
||||
yaml.FilterFunc(func(node *yaml.RNode) (*yaml.RNode, error) {
|
||||
isHelm := node.GetApiVersion() == konfig.BuiltinPluginApiVersion &&
|
||||
node.GetKind() == builtinhelpers.HelmChartInflationGenerator.String()
|
||||
if !isHelm {
|
||||
return node, nil
|
||||
}
|
||||
home, err := node.Pipe(yaml.Lookup("chartHome"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
if home == nil {
|
||||
_, err = lbp.lc.copyChartHomeEntry("")
|
||||
} else {
|
||||
lbp.locPathFn = lbp.lc.copyChartHomeEntry
|
||||
err = lbp.localizeScalar(home)
|
||||
}
|
||||
return node, errors.WrapPrefixf(err, "plugin %s", resid.FromRNode(node))
|
||||
}),
|
||||
fieldspec.Filter{
|
||||
FieldSpec: types.FieldSpec{
|
||||
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.PatchStrategicMergeTransformer.String()},
|
||||
@@ -92,7 +118,6 @@ func (lbp *localizeBuiltinPlugins) Filter(plugins []*yaml.RNode) ([]*yaml.RNode,
|
||||
return lbp.localizeAll(node)
|
||||
},
|
||||
})
|
||||
// TODO(annasong): localize HelmChartInflationGenerator
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
@@ -106,6 +131,7 @@ func (lbp *localizeBuiltinPlugins) localizeAll(node *yaml.RNode) error {
|
||||
// We rely on the build command to throw errors for nodes in
|
||||
// built-in plugins that are sequences when expected to be scalar,
|
||||
// and vice versa.
|
||||
//nolint: exhaustive
|
||||
switch node.YNode().Kind {
|
||||
case yaml.SequenceNode:
|
||||
return errors.Wrap(node.VisitElements(lbp.localizeScalar))
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/internal/generators"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/target"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
@@ -38,10 +38,11 @@ type localizer struct {
|
||||
}
|
||||
|
||||
// Run attempts to localize the kustomization root at target with the given localize arguments
|
||||
func Run(target string, scope string, newDir string, fSys filesys.FileSystem) error {
|
||||
// and returns the path to the created newDir.
|
||||
func Run(target, scope, newDir string, fSys filesys.FileSystem) (string, error) {
|
||||
ldr, args, err := NewLoader(target, scope, newDir, fSys)
|
||||
if err != nil {
|
||||
return errors.Wrap(err)
|
||||
return "", errors.Wrap(err)
|
||||
}
|
||||
defer func() { _ = ldr.Cleanup() }()
|
||||
|
||||
@@ -51,7 +52,7 @@ func Run(target string, scope string, newDir string, fSys filesys.FileSystem) er
|
||||
}
|
||||
dst := args.NewDir.Join(toDst)
|
||||
if err = fSys.MkdirAll(dst); err != nil {
|
||||
return errors.WrapPrefixf(err, "unable to create directory in localize destination")
|
||||
return "", errors.WrapPrefixf(err, "unable to create directory in localize destination")
|
||||
}
|
||||
|
||||
err = (&localizer{
|
||||
@@ -66,9 +67,9 @@ func Run(target string, scope string, newDir string, fSys filesys.FileSystem) er
|
||||
if errCleanup != nil {
|
||||
log.Printf("unable to clean localize destination: %s", errCleanup)
|
||||
}
|
||||
return errors.WrapPrefixf(err, "unable to localize target %q", target)
|
||||
return "", errors.WrapPrefixf(err, "unable to localize target %q", target)
|
||||
}
|
||||
return nil
|
||||
return args.NewDir.String(), nil
|
||||
}
|
||||
|
||||
// localize localizes the root that lc is at
|
||||
@@ -279,6 +280,14 @@ func (lc *localizer) localizeHelmCharts(kust *types.Kustomization) error {
|
||||
return errors.WrapPrefixf(err, "unable to localize helmCharts entry %d valuesFile", i)
|
||||
}
|
||||
kust.HelmCharts[i].ValuesFile = locFile
|
||||
|
||||
for j, valuesFile := range chart.AdditionalValuesFiles {
|
||||
locFile, err = lc.localizeFile(valuesFile)
|
||||
if err != nil {
|
||||
return errors.WrapPrefixf(err, "unable to localize helmCharts entry %d additionalValuesFiles", i)
|
||||
}
|
||||
kust.HelmCharts[i].AdditionalValuesFiles[j] = locFile
|
||||
}
|
||||
}
|
||||
if kust.HelmGlobals != nil {
|
||||
locDir, err := lc.copyChartHomeEntry(kust.HelmGlobals.ChartHome)
|
||||
|
||||
@@ -102,6 +102,14 @@ func addFiles(t *testing.T, fSys filesys.FileSystem, parentDir string, files map
|
||||
}
|
||||
}
|
||||
|
||||
func checkRun(t *testing.T, fSys filesys.FileSystem, target, scope, dst string) {
|
||||
t.Helper()
|
||||
|
||||
actualDst, err := Run(target, scope, dst, fSys)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dst, actualDst)
|
||||
}
|
||||
|
||||
func makeFileSystems(t *testing.T, target string, files map[string]string) (expected filesys.FileSystem, actual filesys.FileSystem) {
|
||||
t.Helper()
|
||||
|
||||
@@ -136,7 +144,7 @@ func reportFSysDiff(t *testing.T, fSysExpected filesys.FileSystem, fSysActual fi
|
||||
actualContent, readErr := fSysActual.ReadFile(path)
|
||||
require.NoError(t, readErr)
|
||||
expectedContent, findErr := fSysExpected.ReadFile(path)
|
||||
assert.NoErrorf(t, findErr, "unexpected file %q", path)
|
||||
require.NoErrorf(t, findErr, "unexpected file %q", path)
|
||||
if findErr == nil {
|
||||
assert.Equal(t, string(expectedContent), string(actualContent))
|
||||
}
|
||||
@@ -161,9 +169,7 @@ func checkLocalizeInTargetSuccess(t *testing.T, files map[string]string) {
|
||||
fSys := makeMemoryFs(t)
|
||||
addFiles(t, fSys, "/a", files)
|
||||
|
||||
err := Run("/a", "/", "dst", fSys)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, fSys, "/a", "/", "/dst")
|
||||
fSysExpected := makeMemoryFs(t)
|
||||
addFiles(t, fSysExpected, "/a", files)
|
||||
addFiles(t, fSysExpected, "/dst/a", files)
|
||||
@@ -179,9 +185,7 @@ namePrefix: my-
|
||||
}
|
||||
fSysExpected, fSysActual := makeFileSystems(t, "/a", kustomization)
|
||||
|
||||
err := Run("/a", "", "/a/b/dst", fSysActual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, fSysActual, "/a", "/a", "/a/b/dst")
|
||||
addFiles(t, fSysExpected, "/a/b/dst", kustomization)
|
||||
checkFSys(t, fSysExpected, fSysActual)
|
||||
}
|
||||
@@ -202,9 +206,7 @@ patches:
|
||||
}
|
||||
fSysExpected, fSysActual := makeFileSystems(t, "/a/b", kustomization)
|
||||
|
||||
err := Run("/a/b", "/", "/a/b/dst", fSysActual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, fSysActual, "/a/b", "/", "/a/b/dst")
|
||||
addFiles(t, fSysExpected, "/a/b/dst/a/b", kustomization)
|
||||
checkFSys(t, fSysExpected, fSysActual)
|
||||
}
|
||||
@@ -259,9 +261,9 @@ func TestLoadUnknownKustFields(t *testing.T) {
|
||||
suffix: invalid`,
|
||||
})
|
||||
|
||||
err := Run("/a", "", "", fSysTest)
|
||||
_, err := Run("/a", "", "", fSysTest)
|
||||
require.EqualError(t, err,
|
||||
`unable to localize target "/a": invalid Kustomization: error unmarshaling JSON: while decoding JSON: json: unknown field "suffix"`)
|
||||
`unable to localize target "/a": invalid Kustomization: json: unknown field "suffix"`)
|
||||
|
||||
checkFSys(t, fSysExpected, fSysTest)
|
||||
}
|
||||
@@ -299,9 +301,7 @@ patches:
|
||||
}
|
||||
expected, actual := makeFileSystems(t, "/alpha/beta/gamma", kustAndPatch)
|
||||
|
||||
err := Run("/alpha/beta/gamma", "/", "", actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, actual, "/alpha/beta/gamma", "/", "/localized-gamma")
|
||||
addFiles(t, expected, "/localized-gamma/alpha/beta/gamma", map[string]string{
|
||||
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
@@ -328,9 +328,7 @@ kind: Kustomization
|
||||
}
|
||||
expected, actual := makeFileSystems(t, "/alpha/beta", targetAndUnreferenced)
|
||||
|
||||
err := Run("/alpha/beta", "/alpha", "/beta", actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, actual, "/alpha/beta", "/alpha", "/beta")
|
||||
addFiles(t, expected, "/beta/beta", map[string]string{
|
||||
"kustomization.yaml": targetAndUnreferenced["kustomization.yaml"],
|
||||
"env": targetAndUnreferenced["env"],
|
||||
@@ -586,15 +584,43 @@ patches:
|
||||
}
|
||||
expected, actual := makeFileSystems(t, "/a/b", kustAndPatch)
|
||||
|
||||
err := Run("/a/b", "", "/dst", actual)
|
||||
_, err := Run("/a/b", "", "/dst", actual)
|
||||
require.EqualError(t, err, `unable to localize target "/a/b": unable to localize patches: invalid file reference: '/a/b/name-DNE.yaml' doesn't exist`)
|
||||
|
||||
checkFSys(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestLocalizePluginsInlineAndFile(t *testing.T) {
|
||||
kustAndPlugins := map[string]string{
|
||||
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
files map[string]string
|
||||
}{
|
||||
{
|
||||
name: "generators",
|
||||
files: map[string]string{
|
||||
"kustomization.yaml": `generators:
|
||||
- generator.yaml
|
||||
- |
|
||||
apiVersion: builtin
|
||||
env: second.properties
|
||||
kind: ConfigMapGenerator
|
||||
metadata:
|
||||
name: inline
|
||||
`,
|
||||
"generator.yaml": `apiVersion: builtin
|
||||
env: first.properties
|
||||
kind: ConfigMapGenerator
|
||||
metadata:
|
||||
name: file
|
||||
`,
|
||||
"first.properties": "APPLE=orange",
|
||||
"second.properties": "BANANA=pear",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "transformers",
|
||||
files: map[string]string{
|
||||
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
transformers:
|
||||
- |
|
||||
@@ -605,16 +631,39 @@ transformers:
|
||||
path: patchSM-one.yaml
|
||||
- patch.yaml
|
||||
`,
|
||||
"patch.yaml": `apiVersion: builtin
|
||||
"patch.yaml": `apiVersion: builtin
|
||||
kind: PatchTransformer
|
||||
metadata:
|
||||
name: file
|
||||
path: patchSM-two.yaml
|
||||
`,
|
||||
"patchSM-one.yaml": podConfiguration,
|
||||
"patchSM-two.yaml": podConfiguration,
|
||||
"patchSM-one.yaml": podConfiguration,
|
||||
"patchSM-two.yaml": podConfiguration,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "validators",
|
||||
files: map[string]string{
|
||||
"kustomization.yaml": `validators:
|
||||
- |
|
||||
apiVersion: builtin
|
||||
kind: ReplacementTransformer
|
||||
metadata:
|
||||
name: inline
|
||||
replacements:
|
||||
- path: first.yaml
|
||||
- second.yaml
|
||||
`,
|
||||
"first.yaml": replacementTransformerWithPath,
|
||||
"second.yaml": replacementTransformerWithPath,
|
||||
"replacement.yaml": replacements,
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
checkLocalizeInTargetSuccess(t, test.files)
|
||||
})
|
||||
}
|
||||
checkLocalizeInTargetSuccess(t, kustAndPlugins)
|
||||
}
|
||||
|
||||
func TestLocalizeMultiplePluginsInEntry(t *testing.T) {
|
||||
@@ -659,9 +708,7 @@ transformers:
|
||||
}
|
||||
expected, actual := makeFileSystems(t, "/a", kustAndPlugins)
|
||||
|
||||
err := Run("/a", "", "/dst", actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, actual, "/a", "/a", "/dst")
|
||||
addFiles(t, expected, "/dst", map[string]string{
|
||||
"kustomization.yaml": kustAndPlugins["kustomization.yaml"],
|
||||
"patch.yaml": fmt.Sprintf(patchf, "patchSM.yaml"),
|
||||
@@ -920,7 +967,7 @@ metadata:
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
expected, actual := makeFileSystems(t, "/", test.files)
|
||||
|
||||
err := Run("/", "", "/dst", actual)
|
||||
_, err := Run("/", "", "/dst", actual)
|
||||
|
||||
var actualErr ResourceLoadError
|
||||
require.ErrorAs(t, err, &actualErr)
|
||||
@@ -974,7 +1021,7 @@ func TestLocalizeBuiltinPlugins_Errors(t *testing.T) {
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
expected, actual := makeFileSystems(t, "/a", test.files)
|
||||
err := Run("/a", "", "/dst", actual)
|
||||
_, err := Run("/a", "", "/dst", actual)
|
||||
const errPrefix = `unable to localize target "/a"`
|
||||
require.EqualError(t, err, fmt.Sprintf(
|
||||
"%s: %s: %s", errPrefix, test.fieldSpecErr, test.locErr))
|
||||
@@ -1094,9 +1141,7 @@ namespace: kustomize-namespace
|
||||
}
|
||||
expected, actual := makeFileSystems(t, "/alpha", kustAndComponents)
|
||||
|
||||
err := Run("/alpha/beta/gamma", "/alpha", "/alpha/beta/dst", actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, actual, "/alpha/beta/gamma", "/alpha", "/alpha/beta/dst")
|
||||
cleanedFiles := map[string]string{
|
||||
"beta/gamma/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
components:
|
||||
@@ -1159,9 +1204,7 @@ namePrefix: my-
|
||||
}
|
||||
expected, actual := makeFileSystems(t, "/a/b", kustAndResources)
|
||||
|
||||
err := Run("/a/b", "/", "", actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, actual, "/a/b", "/", "/localized-b")
|
||||
addFiles(t, expected, "/localized-b/a/b", kustAndResources)
|
||||
checkFSys(t, expected, actual)
|
||||
}
|
||||
@@ -1176,7 +1219,7 @@ resources:
|
||||
}
|
||||
expected, actual := makeFileSystems(t, "/a", kustAndResources)
|
||||
|
||||
err := Run("/a", "/", "", actual)
|
||||
_, err := Run("/a", "/", "", actual)
|
||||
|
||||
const expectedFileErr = `invalid file reference: '/a/b' must resolve to a file`
|
||||
const expectedRootErr = `unable to localize root "b": unable to find one of 'kustomization.yaml', 'kustomization.yml' or 'Kustomization' in directory '/a/b'`
|
||||
@@ -1230,8 +1273,13 @@ func TestLocalizeHelmCharts(t *testing.T) {
|
||||
- includeCRDs: true
|
||||
name: localize-valuesFile
|
||||
valuesFile: file
|
||||
- additionalValuesFiles:
|
||||
- another
|
||||
- third
|
||||
`,
|
||||
"file": valuesFile,
|
||||
"another": valuesFile,
|
||||
"third": valuesFile,
|
||||
"charts/nothing-to-localize/values.yaml": valuesFile,
|
||||
"charts/localize-valuesFile/values.yaml": valuesFile,
|
||||
},
|
||||
@@ -1273,9 +1321,7 @@ func TestLocalizeHelmChartsNoDefault(t *testing.T) {
|
||||
}
|
||||
expected, actual := makeFileSystems(t, "/a", files)
|
||||
|
||||
err := Run("/a", "", "/dst", actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, actual, "/a", "/a", "/dst")
|
||||
addFiles(t, expected, "/dst", map[string]string{
|
||||
"kustomization.yaml": files["kustomization.yaml"],
|
||||
"home/name/values.yaml": valuesFile,
|
||||
@@ -1389,9 +1435,7 @@ helmGlobals:
|
||||
t.Run(name, func(t *testing.T) {
|
||||
expected, actual := makeFileSystems(t, "/a/b", test.files)
|
||||
|
||||
err := Run("/a/b", "/a/b", "/dst", actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, actual, "/a/b", "/a/b", "/dst")
|
||||
addFiles(t, expected, "/dst", test.copiedFiles)
|
||||
checkFSys(t, expected, actual)
|
||||
})
|
||||
@@ -1408,9 +1452,7 @@ func TestCopyChartHomeEmpty(t *testing.T) {
|
||||
require.NoError(t, actual.Mkdir("/a/home"))
|
||||
require.NoError(t, expected.Mkdir("/a/home"))
|
||||
|
||||
err := Run("/a", "", "/dst", actual)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkRun(t, actual, "/a", "/a", "/dst")
|
||||
addFiles(t, expected, "/dst", kustomization)
|
||||
require.NoError(t, expected.Mkdir("/dst/home"))
|
||||
checkFSys(t, expected, actual)
|
||||
@@ -1452,7 +1494,7 @@ func TestCopyChartHomeError(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
expected, actual := makeFileSystems(t, "/", test.files)
|
||||
|
||||
err := Run("/a/b", "/a", "/dst", actual)
|
||||
_, err := Run("/a/b", "/a", "/dst", actual)
|
||||
const prefix = `unable to localize target "/a/b"`
|
||||
require.EqualError(t, err, fmt.Sprintf("%s: %s", prefix, test.err))
|
||||
|
||||
@@ -1461,6 +1503,67 @@ func TestCopyChartHomeError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLocalizeGeneratorsHelm(t *testing.T) {
|
||||
files := map[string]string{
|
||||
"kustomization.yaml": `generators:
|
||||
- default.yaml
|
||||
- explicit.yaml
|
||||
`,
|
||||
"default.yaml": `apiVersion: builtin
|
||||
kind: HelmChartInflationGenerator
|
||||
metadata:
|
||||
name: no-explicit-references
|
||||
name: minecraft
|
||||
releaseName: moria
|
||||
repo: https://itzg.github.io/minecraft-server-charts
|
||||
version: 3.1.3
|
||||
`,
|
||||
"explicit.yaml": `additionalValuesFiles:
|
||||
- time.yaml
|
||||
- life.yaml
|
||||
- light.yaml
|
||||
apiVersion: builtin
|
||||
chartHome: home
|
||||
kind: HelmChartInflationGenerator
|
||||
metadata:
|
||||
name: explicit-references
|
||||
name: mapleStory
|
||||
valuesFile: mapleValues.yaml
|
||||
`,
|
||||
"time.yaml": valuesFile,
|
||||
"life.yaml": valuesFile,
|
||||
"light.yaml": valuesFile,
|
||||
"mapleValues.yaml": valuesFile,
|
||||
"home/mapleStory/values.yaml": valuesFile,
|
||||
"charts/minecraft/values.yaml": valuesFile,
|
||||
}
|
||||
checkLocalizeInTargetSuccess(t, files)
|
||||
}
|
||||
|
||||
func TestLocalizeGeneratorsNoHelm(t *testing.T) {
|
||||
files := map[string]string{
|
||||
"kustomization.yaml": `generators:
|
||||
- configMap.yaml
|
||||
`,
|
||||
"configMap.yaml": `apiVersion: builtin
|
||||
kind: ConfigMapGenerator
|
||||
literals:
|
||||
- APPLE=orange
|
||||
metadata:
|
||||
name: not-helm-shouldn't-copy-default-helm-chart-home
|
||||
`,
|
||||
"charts/minecraft/values.yaml": valuesFile,
|
||||
}
|
||||
expected, actual := makeFileSystems(t, "/a", files)
|
||||
|
||||
checkRun(t, actual, "/a", "/a", "/dst")
|
||||
addFiles(t, expected, "/dst", map[string]string{
|
||||
"kustomization.yaml": files["kustomization.yaml"],
|
||||
"configMap.yaml": files["configMap.yaml"],
|
||||
})
|
||||
checkFSys(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestLocalizeEmpty(t *testing.T) {
|
||||
for name, kustomization := range map[string]string{
|
||||
"file": `configurations:
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/internal/git"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
@@ -6,6 +6,7 @@ package localizer_test
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -37,6 +38,9 @@ func TestLocalLoadNewAndCleanup(t *testing.T) {
|
||||
|
||||
var buf bytes.Buffer
|
||||
log.SetOutput(&buf)
|
||||
defer func() {
|
||||
log.SetOutput(os.Stderr)
|
||||
}()
|
||||
// typical setup
|
||||
ldr, args, err := NewLoader("a", "/", "/newDir", fSys)
|
||||
req.NoError(err)
|
||||
@@ -223,6 +227,9 @@ func TestNewLocLoaderFails(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
log.SetOutput(&buf)
|
||||
defer func() {
|
||||
log.SetOutput(os.Stderr)
|
||||
}()
|
||||
|
||||
_, _, err := NewLoader(params.target, params.scope, params.dest, makeMemoryFs(t))
|
||||
require.Error(t, err)
|
||||
|
||||
@@ -33,7 +33,7 @@ func loadDefaultConfig(
|
||||
// makeTransformerConfigFromBytes returns a TransformerConfig object from bytes
|
||||
func makeTransformerConfigFromBytes(data []byte) (*TransformerConfig, error) {
|
||||
var t TransformerConfig
|
||||
err := yaml.Unmarshal(data, &t)
|
||||
err := yaml.UnmarshalStrict(data, &t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@ package builtinconfig
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||
@@ -44,3 +45,55 @@ namePrefix:
|
||||
t.Fatalf("expected %v\n but go6t %v\n", expected, tCfg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadDefaultConfigsFromFilesWithMissingFields(t *testing.T) {
|
||||
fSys := filesys.MakeFsInMemory()
|
||||
filePathContainsTypo := "config_contains_typo.yaml"
|
||||
if err := fSys.WriteFile(filePathContainsTypo, []byte(`
|
||||
namoPrefix:
|
||||
- path: nameprefix/path
|
||||
kind: SomeKind
|
||||
`)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ldr, err := loader.NewLoader(
|
||||
loader.RestrictionRootOnly, filesys.Separator, fSys)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
errMsg := "error unmarshaling JSON: while decoding JSON: json: unknown field"
|
||||
_, err = loadDefaultConfig(ldr, []string{filePathContainsTypo})
|
||||
if err == nil {
|
||||
t.Fatalf("expected to fail unmarshal yaml, but got nil %s", filePathContainsTypo)
|
||||
}
|
||||
if !strings.Contains(err.Error(), errMsg) {
|
||||
t.Fatalf("expected error %s, but got %s", errMsg, err)
|
||||
}
|
||||
}
|
||||
|
||||
// please remove this failing test after implements the labels support
|
||||
func TestLoadDefaultConfigsFromFilesWithMissingFieldsLabels(t *testing.T) {
|
||||
fSys := filesys.MakeFsInMemory()
|
||||
filePathContainsTypo := "config_contains_typo.yaml"
|
||||
if err := fSys.WriteFile(filePathContainsTypo, []byte(`
|
||||
labels:
|
||||
- path: spec/podTemplate/metadata/labels
|
||||
create: true
|
||||
kind: FlinkDeployment
|
||||
`)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ldr, err := loader.NewLoader(
|
||||
loader.RestrictionRootOnly, filesys.Separator, fSys)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
errMsg := "error unmarshaling JSON: while decoding JSON: json: unknown field"
|
||||
_, err = loadDefaultConfig(ldr, []string{filePathContainsTypo})
|
||||
if err == nil {
|
||||
t.Fatalf("expected to fail unmarshal yaml, but got nil %s", filePathContainsTypo)
|
||||
}
|
||||
if !strings.Contains(err.Error(), errMsg) {
|
||||
t.Fatalf("expected error %s, but got %s", errMsg, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,8 @@ type NameBackReferences struct {
|
||||
// TODO: rename json 'fieldSpecs' to 'referrers' for clarity.
|
||||
// This will, however, break anyone using a custom config.
|
||||
Referrers types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
|
||||
|
||||
// Note: If any new pointer based members are added, DeepCopy needs to be updated
|
||||
}
|
||||
|
||||
func (n NameBackReferences) String() string {
|
||||
@@ -66,6 +68,17 @@ func (s nbrSlice) Less(i, j int) bool {
|
||||
return s[i].Gvk.IsLessThan(s[j].Gvk)
|
||||
}
|
||||
|
||||
// DeepCopy returns a new copy of nbrSlice
|
||||
func (s nbrSlice) DeepCopy() nbrSlice {
|
||||
ret := make(nbrSlice, len(s))
|
||||
copy(ret, s)
|
||||
for i, slice := range ret {
|
||||
ret[i].Referrers = slice.Referrers.DeepCopy()
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s nbrSlice) mergeAll(o nbrSlice) (result nbrSlice, err error) {
|
||||
result = s
|
||||
for _, r := range o {
|
||||
|
||||
@@ -95,3 +95,29 @@ func TestMergeAll(t *testing.T) {
|
||||
t.Fatalf("expected\n %v\n but got\n %v\n", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNbrSlice_DeepCopy(t *testing.T) {
|
||||
original := make(nbrSlice, 2, 4)
|
||||
original[0] = NameBackReferences{Gvk: resid.FromKind("A"), Referrers: types.FsSlice{{Path: "a"}}}
|
||||
original[1] = NameBackReferences{Gvk: resid.FromKind("B"), Referrers: types.FsSlice{{Path: "b"}}}
|
||||
|
||||
copied := original.DeepCopy()
|
||||
|
||||
original, _ = original.mergeOne(NameBackReferences{Gvk: resid.FromKind("C"), Referrers: types.FsSlice{{Path: "c"}}})
|
||||
|
||||
// perform mutations which should not affect original
|
||||
copied.Swap(0, 1)
|
||||
copied[0].Referrers[0].Path = "very b" // ensure Referrers are not shared
|
||||
_, _ = copied.mergeOne(NameBackReferences{Gvk: resid.FromKind("D"), Referrers: types.FsSlice{{Path: "d"}}})
|
||||
|
||||
// if DeepCopy does not work, original would be {very b,a,d} instead of {a,b,c}
|
||||
expected := nbrSlice{
|
||||
{Gvk: resid.FromKind("A"), Referrers: types.FsSlice{{Path: "a"}}},
|
||||
{Gvk: resid.FromKind("B"), Referrers: types.FsSlice{{Path: "b"}}},
|
||||
{Gvk: resid.FromKind("C"), Referrers: types.FsSlice{{Path: "c"}}},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(original, expected) {
|
||||
t.Fatalf("original affected by mutations to copied object:\ngot\t%+v,\nexpected: %+v", original, expected)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,17 @@ package builtinconfig
|
||||
import (
|
||||
"log"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/konfig/builtinpluginconsts"
|
||||
"sigs.k8s.io/kustomize/api/internal/konfig/builtinpluginconsts"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
)
|
||||
|
||||
// TransformerConfig holds the data needed to perform transformations.
|
||||
type TransformerConfig struct {
|
||||
// if any fields are added, update the DeepCopy implementation
|
||||
NamePrefix types.FsSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"`
|
||||
NameSuffix types.FsSlice `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"`
|
||||
NameSpace types.FsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||
@@ -32,14 +34,43 @@ func MakeEmptyConfig() *TransformerConfig {
|
||||
return &TransformerConfig{}
|
||||
}
|
||||
|
||||
// DeepCopy returns a new copy of TransformerConfig
|
||||
func (t *TransformerConfig) DeepCopy() *TransformerConfig {
|
||||
return &TransformerConfig{
|
||||
NamePrefix: t.NamePrefix.DeepCopy(),
|
||||
NameSuffix: t.NameSuffix.DeepCopy(),
|
||||
NameSpace: t.NameSpace.DeepCopy(),
|
||||
CommonLabels: t.CommonLabels.DeepCopy(),
|
||||
TemplateLabels: t.TemplateLabels.DeepCopy(),
|
||||
CommonAnnotations: t.CommonAnnotations.DeepCopy(),
|
||||
NameReference: t.NameReference.DeepCopy(),
|
||||
VarReference: t.VarReference.DeepCopy(),
|
||||
Images: t.Images.DeepCopy(),
|
||||
Replicas: t.Replicas.DeepCopy(),
|
||||
}
|
||||
}
|
||||
|
||||
// the default transformer config is initialized by MakeDefaultConfig,
|
||||
// and must only be accessed via that function.
|
||||
var (
|
||||
initDefaultConfig sync.Once //nolint:gochecknoglobals
|
||||
defaultConfig *TransformerConfig //nolint:gochecknoglobals
|
||||
)
|
||||
|
||||
// MakeDefaultConfig returns a default TransformerConfig.
|
||||
func MakeDefaultConfig() *TransformerConfig {
|
||||
c, err := makeTransformerConfigFromBytes(
|
||||
builtinpluginconsts.GetDefaultFieldSpecs())
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to make default transformconfig: %v", err)
|
||||
}
|
||||
return c
|
||||
// parsing is expensive when having a large tree with many kustomization modules, so only do it once
|
||||
initDefaultConfig.Do(func() {
|
||||
var err error
|
||||
defaultConfig, err = makeTransformerConfigFromBytes(
|
||||
builtinpluginconsts.GetDefaultFieldSpecs())
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to make default transformconfig: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
// return a copy to avoid any mutations to protect the reference copy
|
||||
return defaultConfig.DeepCopy()
|
||||
}
|
||||
|
||||
// MakeTransformerConfig returns a merger of custom config,
|
||||
|
||||
@@ -173,3 +173,22 @@ func TestMerge(t *testing.T) {
|
||||
t.Fatalf("expected: %v\n but got: %v\n", cfga, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeDefaultConfig_mutation(t *testing.T) {
|
||||
a := MakeDefaultConfig()
|
||||
|
||||
// mutate
|
||||
a.NameReference[0].Kind = "mutated"
|
||||
a.NameReference = a.NameReference[:1]
|
||||
|
||||
clean := MakeDefaultConfig()
|
||||
if clean.NameReference[0].Kind == "mutated" {
|
||||
t.Errorf("MakeDefaultConfig() did not return a clean copy: %+v", clean.NameReference)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMakeDefaultConfig(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = MakeDefaultConfig()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package execplugin
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
@@ -21,6 +22,7 @@ import (
|
||||
|
||||
const (
|
||||
tmpConfigFilePrefix = "kust-plugin-config-"
|
||||
maxArgStringLength = 131071
|
||||
)
|
||||
|
||||
// ExecPlugin record the name and args of an executable
|
||||
@@ -169,23 +171,35 @@ func (p *ExecPlugin) invokePlugin(input []byte) ([]byte, error) {
|
||||
p.path, append([]string{f.Name()}, p.args...)...)
|
||||
cmd.Env = p.getEnv()
|
||||
cmd.Stdin = bytes.NewReader(input)
|
||||
cmd.Stderr = os.Stderr
|
||||
var stdErr bytes.Buffer
|
||||
cmd.Stderr = &stdErr
|
||||
if _, err := os.Stat(p.h.Loader().Root()); err == nil {
|
||||
cmd.Dir = p.h.Loader().Root()
|
||||
}
|
||||
result, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, errors.WrapPrefixf(
|
||||
err, "failure in plugin configured via %s; %v",
|
||||
f.Name(), err.Error())
|
||||
fmt.Errorf("failure in plugin configured via %s; %w",
|
||||
f.Name(), err), stdErr.String())
|
||||
}
|
||||
return result, os.Remove(f.Name())
|
||||
}
|
||||
|
||||
func (p *ExecPlugin) getEnv() []string {
|
||||
env := os.Environ()
|
||||
env = append(env,
|
||||
"KUSTOMIZE_PLUGIN_CONFIG_STRING="+string(p.cfg),
|
||||
"KUSTOMIZE_PLUGIN_CONFIG_ROOT="+p.h.Loader().Root())
|
||||
pluginConfigString := "KUSTOMIZE_PLUGIN_CONFIG_STRING=" + string(p.cfg)
|
||||
if len(pluginConfigString) <= maxArgStringLength {
|
||||
env = append(env, pluginConfigString)
|
||||
} else {
|
||||
log.Printf("KUSTOMIZE_PLUGIN_CONFIG_STRING exceeds hard limit of %d characters, the environment variable "+
|
||||
"will be omitted", maxArgStringLength)
|
||||
}
|
||||
pluginConfigRoot := "KUSTOMIZE_PLUGIN_CONFIG_ROOT=" + p.h.Loader().Root()
|
||||
if len(pluginConfigRoot) <= maxArgStringLength {
|
||||
env = append(env, pluginConfigRoot)
|
||||
} else {
|
||||
log.Printf("KUSTOMIZE_PLUGIN_CONFIG_ROOT exceeds hard limit of %d characters, the environment variable "+
|
||||
"will be omitted", maxArgStringLength)
|
||||
}
|
||||
return env
|
||||
}
|
||||
|
||||
@@ -10,16 +10,22 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
fLdr "sigs.k8s.io/kustomize/api/internal/loader"
|
||||
. "sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
||||
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
||||
fLdr "sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
const (
|
||||
expectedLargeConfigMap = `{"apiVersion":"v1","data":{"password":"password","username":"user"},"kind":"ConfigMap",` +
|
||||
`"metadata":{"annotations":{"internal.config.kubernetes.io/generatorBehavior":"unspecified",` +
|
||||
`"internal.config.kubernetes.io/needsHashSuffix":"enabled"},"name":"example-configmap-test"}}`
|
||||
)
|
||||
|
||||
func TestExecPluginConfig(t *testing.T) {
|
||||
fSys := filesys.MakeFsInMemory()
|
||||
err := fSys.WriteFile("sed-input.txt", []byte(`
|
||||
@@ -125,3 +131,104 @@ func TestExecPlugin_ErrIfNotExecutable(t *testing.T) {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestExecPluginLarge loads PluginConfigs of various (large) sizes. It tests if the env variable is kept below the
|
||||
// maximum of 131072 bytes.
|
||||
func TestExecPluginLarge(t *testing.T) {
|
||||
// Skip this test on windows.
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skipf("always returns nil on Windows")
|
||||
}
|
||||
|
||||
// Add executable plugin.
|
||||
srcRoot, err := utils.DeterminePluginSrcRoot(filesys.MakeFsOnDisk())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
executablePlugin := filepath.Join(
|
||||
srcRoot, "someteam.example.com", "v1", "bashedconfigmap", "BashedConfigMap")
|
||||
p := NewExecPlugin(executablePlugin)
|
||||
err = p.ErrIfNotExecutable()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
|
||||
// Create a fake filesystem.
|
||||
fSys := filesys.MakeFsInMemory()
|
||||
|
||||
// Load plugin config.
|
||||
ldr, err := fLdr.NewLoader(
|
||||
fLdr.RestrictionRootOnly, filesys.Separator, fSys)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pvd := provider.NewDefaultDepProvider()
|
||||
rf := resmap.NewFactory(pvd.GetResourceFactory())
|
||||
pc := types.DisabledPluginConfig()
|
||||
|
||||
// Test for various lengths. 131071 is the max length that we can have for any given env var in Bytes.
|
||||
tcs := []struct {
|
||||
length int
|
||||
char rune
|
||||
}{
|
||||
{1000, 'a'},
|
||||
{131071, 'a'},
|
||||
{131072, 'a'},
|
||||
{200000, 'a'},
|
||||
{131071, '安'},
|
||||
{131074, '安'},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Logf("Testing with an env var length of %d and character %c", tc.length, tc.char)
|
||||
pluginConfig, err := rf.RF().FromBytes(buildLargePluginConfig(tc.length, tc.char))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
yaml, err := pluginConfig.AsYAML()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
err = p.Config(resmap.NewPluginHelpers(ldr, pvd.GetFieldValidator(), rf, pc), yaml)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
resMap, err := p.Generate()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
rNodeSlices := resMap.ToRNodeSlice()
|
||||
for _, rNodeSlice := range rNodeSlices {
|
||||
json, err := rNodeSlice.MarshalJSON()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if string(json) != expectedLargeConfigMap {
|
||||
t.Fatalf("expected generated JSON to match %q, but got %q instead",
|
||||
expectedLargeConfigMap, string(json))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// buildLargePluginConfig builds a plugin configuration of length: length - len("KUSTOMIZE_PLUGIN_CONFIG_STRING=")
|
||||
// This allows us to create an environment variable KUSTOMIZE_PLUGIN_CONFIG_STRING=<plugin content> with the exact
|
||||
// length that's provided in the length parameter. Used as a helper for TestExecPluginLarge.
|
||||
func buildLargePluginConfig(length int, char rune) []byte {
|
||||
length -= len("KUSTOMIZE_PLUGIN_CONFIG_STRING=")
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteString("apiVersion: someteam.example.com/v1\n")
|
||||
sb.WriteString("kind: BashedConfigMap\n")
|
||||
sb.WriteString("metadata:\n")
|
||||
sb.WriteString(" name: some-random-name\n")
|
||||
sb.WriteString("argsOneLiner: \"user password\"\n")
|
||||
sb.WriteString("customArg: ")
|
||||
|
||||
// Now, fill up parameter customArg: until we reach the desired length. Account for the fact that runes can be
|
||||
// 1 to 4 Bytes each.
|
||||
upperBound := length - sb.Len()
|
||||
for i := 0; i < upperBound-len(string(char)); i += len(string(char)) {
|
||||
sb.WriteRune(char)
|
||||
}
|
||||
return []byte(sb.String())
|
||||
}
|
||||
|
||||
62
api/internal/plugins/loader/load_go_plugin.go
Normal file
62
api/internal/plugins/loader/load_go_plugin.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2024 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//go:build !kustomize_disable_go_plugin_support
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"plugin"
|
||||
"reflect"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||
)
|
||||
|
||||
// registry is a means to avoid trying to load the same .so file
|
||||
// into memory more than once, which results in an error.
|
||||
// Each test makes its own loader, and tries to load its own plugins,
|
||||
// but the loaded .so files are in shared memory, so one will get
|
||||
// "this plugin already loaded" errors if the registry is maintained
|
||||
// as a Loader instance variable. So make it a package variable.
|
||||
var registry = make(map[string]resmap.Configurable) //nolint:gochecknoglobals
|
||||
|
||||
func copyPlugin(c resmap.Configurable) resmap.Configurable {
|
||||
indirect := reflect.Indirect(reflect.ValueOf(c))
|
||||
newIndirect := reflect.New(indirect.Type())
|
||||
newIndirect.Elem().Set(reflect.ValueOf(indirect.Interface()))
|
||||
newNamed := newIndirect.Interface()
|
||||
return newNamed.(resmap.Configurable) //nolint:forcetypeassert
|
||||
}
|
||||
|
||||
func (l *Loader) loadGoPlugin(id resid.ResId, absPath string) (resmap.Configurable, error) {
|
||||
regId := relativePluginPath(id)
|
||||
if c, ok := registry[regId]; ok {
|
||||
return copyPlugin(c), nil
|
||||
}
|
||||
if !utils.FileExists(absPath) {
|
||||
return nil, fmt.Errorf(
|
||||
"expected file with Go object code at: %s", absPath)
|
||||
}
|
||||
log.Printf("Attempting plugin load from %q", absPath)
|
||||
p, err := plugin.Open(absPath)
|
||||
if err != nil {
|
||||
return nil, errors.WrapPrefixf(err, "plugin %s fails to load", absPath)
|
||||
}
|
||||
symbol, err := p.Lookup(konfig.PluginSymbol)
|
||||
if err != nil {
|
||||
return nil, errors.WrapPrefixf(
|
||||
err, "plugin %s doesn't have symbol %s",
|
||||
regId, konfig.PluginSymbol)
|
||||
}
|
||||
c, ok := symbol.(resmap.Configurable)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("plugin %q not configurable", regId)
|
||||
}
|
||||
registry[regId] = c
|
||||
return copyPlugin(c), nil
|
||||
}
|
||||
24
api/internal/plugins/loader/load_go_plugin_disabled.go
Normal file
24
api/internal/plugins/loader/load_go_plugin_disabled.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2024 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// The build tag "kustomize_disable_go_plugin_support" is used to deactivate the
|
||||
// kustomize API's dependency on the "plugins" package. This is beneficial for
|
||||
// applications that need to embed it but do not have requirements for dynamic
|
||||
// Go plugins.
|
||||
// Including plugins as a dependency can lead to an increase in binary size due
|
||||
// to the population of ELF's sections such as .dynsym and .dynstr.
|
||||
// By utilizing this flag, applications have the flexibility to exclude the
|
||||
// import if they do not require support for dynamic Go plugins.
|
||||
//go:build kustomize_disable_go_plugin_support
|
||||
|
||||
package loader
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/resid"
|
||||
)
|
||||
|
||||
func (l *Loader) loadGoPlugin(_ resid.ResId, _ string) (resmap.Configurable, error) {
|
||||
return nil, errors.New("plugin load is disabled")
|
||||
}
|
||||
@@ -5,18 +5,14 @@ package loader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/fnplugin"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/utils"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
@@ -287,46 +283,3 @@ func (l *Loader) loadExecOrGoPlugin(resId resid.ResId) (resmap.Configurable, err
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// registry is a means to avoid trying to load the same .so file
|
||||
// into memory more than once, which results in an error.
|
||||
// Each test makes its own loader, and tries to load its own plugins,
|
||||
// but the loaded .so files are in shared memory, so one will get
|
||||
// "this plugin already loaded" errors if the registry is maintained
|
||||
// as a Loader instance variable. So make it a package variable.
|
||||
var registry = make(map[string]resmap.Configurable)
|
||||
|
||||
func (l *Loader) loadGoPlugin(id resid.ResId, absPath string) (resmap.Configurable, error) {
|
||||
regId := relativePluginPath(id)
|
||||
if c, ok := registry[regId]; ok {
|
||||
return copyPlugin(c), nil
|
||||
}
|
||||
if !utils.FileExists(absPath) {
|
||||
return nil, fmt.Errorf(
|
||||
"expected file with Go object code at: %s", absPath)
|
||||
}
|
||||
log.Printf("Attempting plugin load from '%s'", absPath)
|
||||
p, err := plugin.Open(absPath)
|
||||
if err != nil {
|
||||
return nil, errors.WrapPrefixf(err, "plugin %s fails to load", absPath)
|
||||
}
|
||||
symbol, err := p.Lookup(konfig.PluginSymbol)
|
||||
if err != nil {
|
||||
return nil, errors.WrapPrefixf(
|
||||
err, "plugin %s doesn't have symbol %s",
|
||||
regId, konfig.PluginSymbol)
|
||||
}
|
||||
c, ok := symbol.(resmap.Configurable)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("plugin '%s' not configurable", regId)
|
||||
}
|
||||
registry[regId] = c
|
||||
return copyPlugin(c), nil
|
||||
}
|
||||
|
||||
func copyPlugin(c resmap.Configurable) resmap.Configurable {
|
||||
indirect := reflect.Indirect(reflect.ValueOf(c))
|
||||
newIndirect := reflect.New(indirect.Type())
|
||||
newIndirect.Elem().Set(reflect.ValueOf(indirect.Interface()))
|
||||
newNamed := newIndirect.Interface()
|
||||
return newNamed.(resmap.Configurable)
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
. "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
@@ -53,7 +52,7 @@ func makeConfigMap(rf *resource.Factory, name, behavior string, hashValue *strin
|
||||
return r
|
||||
}
|
||||
|
||||
func makeConfigMapOptions(rf *resource.Factory, name, behavior string, disableHash bool) *resource.Resource {
|
||||
func makeConfigMapOptions(rf *resource.Factory, name, behavior string, disableHash bool) (*resource.Resource, error) {
|
||||
return rf.FromMapAndOption(map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
@@ -89,12 +88,16 @@ func TestUpdateResourceOptions(t *testing.T) {
|
||||
name := fmt.Sprintf("test%d", i)
|
||||
err := in.Append(makeConfigMap(rf, name, c.behavior, c.hashValue))
|
||||
require.NoError(t, err)
|
||||
err = expected.Append(makeConfigMapOptions(rf, name, c.behavior, !c.needsHash))
|
||||
config, err := makeConfigMapOptions(rf, name, c.behavior, !c.needsHash)
|
||||
if err != nil {
|
||||
t.Errorf("expected new instance with an options but got error: %v", err)
|
||||
}
|
||||
err = expected.Append(config)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
actual, err := UpdateResourceOptions(in)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, expected.ErrorIfNotEqualLists(actual))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, expected.ErrorIfNotEqualLists(actual))
|
||||
}
|
||||
|
||||
func TestUpdateResourceOptionsWithInvalidHashAnnotationValues(t *testing.T) {
|
||||
|
||||
@@ -13,12 +13,12 @@ import (
|
||||
"sigs.k8s.io/kustomize/api/internal/accumulator"
|
||||
"sigs.k8s.io/kustomize/api/internal/builtins"
|
||||
"sigs.k8s.io/kustomize/api/internal/kusterr"
|
||||
load "sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/builtinhelpers"
|
||||
"sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
load "sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
@@ -73,6 +73,11 @@ func (kt *KustTarget) Load() error {
|
||||
|
||||
k.FixKustomization()
|
||||
|
||||
// check that Kustomization is empty
|
||||
if err := k.CheckEmpty(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
errs := k.EnforceFields()
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf(
|
||||
@@ -197,10 +202,6 @@ func (kt *KustTarget) accumulateTarget(ra *accumulator.ResAccumulator) (
|
||||
if err != nil {
|
||||
return nil, errors.WrapPrefixf(err, "accumulating resources")
|
||||
}
|
||||
ra, err = kt.accumulateComponents(ra, kt.kustomization.Components)
|
||||
if err != nil {
|
||||
return nil, errors.WrapPrefixf(err, "accumulating components")
|
||||
}
|
||||
tConfig, err := builtinconfig.MakeTransformerConfig(
|
||||
kt.ldr, kt.kustomization.Configurations)
|
||||
if err != nil {
|
||||
@@ -225,6 +226,14 @@ func (kt *KustTarget) accumulateTarget(ra *accumulator.ResAccumulator) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// components are expected to execute after reading resources and adding generators ,before applying transformers and validation.
|
||||
// https://github.com/kubernetes-sigs/kustomize/pull/5170#discussion_r1212101287
|
||||
ra, err = kt.accumulateComponents(ra, kt.kustomization.Components)
|
||||
if err != nil {
|
||||
return nil, errors.WrapPrefixf(err, "accumulating components")
|
||||
}
|
||||
|
||||
err = kt.runTransformers(ra)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -416,7 +425,14 @@ func (kt *KustTarget) accumulateResources(
|
||||
}
|
||||
ldr, err := kt.ldr.New(path)
|
||||
if err != nil {
|
||||
if kusterr.IsMalformedYAMLError(errF) { // Some error occurred while tyring to decode YAML file
|
||||
// If accumulateFile found malformed YAML and there was a failure
|
||||
// loading the resource as a base, then the resource is likely a
|
||||
// file. The loader failure message is unnecessary, and could be
|
||||
// confusing. Report only the file load error.
|
||||
//
|
||||
// However, a loader timeout implies there is a git repo at the
|
||||
// path. In that case, both errors could be important.
|
||||
if kusterr.IsMalformedYAMLError(errF) && !utils.IsErrTimeout(err) {
|
||||
return nil, errF
|
||||
}
|
||||
return nil, errors.WrapPrefixf(
|
||||
|
||||
@@ -8,12 +8,14 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
. "sigs.k8s.io/kustomize/api/internal/target"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/utils"
|
||||
"sigs.k8s.io/kustomize/api/pkg/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
@@ -79,6 +81,7 @@ func TestLoad(t *testing.T) {
|
||||
k: types.Kustomization{
|
||||
TypeMeta: expectedTypeMeta,
|
||||
},
|
||||
errContains: "kustomization.yaml is empty",
|
||||
},
|
||||
"nonsenseLatin": {
|
||||
errContains: "found a tab character that violates indentation",
|
||||
@@ -284,15 +287,15 @@ metadata:
|
||||
}
|
||||
expected.RemoveBuildAnnotations()
|
||||
expYaml, err := expected.AsYaml()
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
kt := makeKustTargetWithRf(t, th.GetFSys(), "/whatever", pvd)
|
||||
assert.NoError(t, kt.Load())
|
||||
require.NoError(t, kt.Load())
|
||||
actual, err := kt.MakeCustomizedResMap()
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
actual.RemoveBuildAnnotations()
|
||||
actYaml, err := actual.AsYaml()
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, string(expYaml), string(actYaml))
|
||||
}
|
||||
|
||||
@@ -312,19 +315,21 @@ configurations:
|
||||
th.WriteF("/merge-config/name-prefix-rules.yaml", `
|
||||
namePrefix:
|
||||
- path: metadata/name
|
||||
apiVersion: v1
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
- path: metadata/name
|
||||
apiVersion: v1
|
||||
version: v1
|
||||
kind: Secret
|
||||
`)
|
||||
th.WriteF("/merge-config/name-suffix-rules.yaml", `
|
||||
nameSuffix:
|
||||
- path: metadata/name
|
||||
apiVersion: v1
|
||||
version: v1
|
||||
kind: ConfigMap
|
||||
- path: metadata/name
|
||||
apiVersion: v1
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
`)
|
||||
th.WriteF("/merge-config/deployment.yaml", `
|
||||
@@ -422,7 +427,7 @@ func TestDuplicateExternalGeneratorsForbidden(t *testing.T) {
|
||||
configPath: another_config.json
|
||||
`)
|
||||
_, err := makeAndLoadKustTarget(t, th.GetFSys(), "/generator").AccumulateTarget()
|
||||
assert.Error(t, err)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "may not add resource with an already registered id: ManifestGenerator.v1.generators.example/ManifestGenerator")
|
||||
}
|
||||
|
||||
@@ -451,6 +456,83 @@ func TestDuplicateExternalTransformersForbidden(t *testing.T) {
|
||||
value: 'fail'
|
||||
`)
|
||||
_, err := makeAndLoadKustTarget(t, th.GetFSys(), "/transformer").AccumulateTarget()
|
||||
assert.Error(t, err)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "may not add resource with an already registered id: ValueAnnotator.v1.transformers.example.co/notImportantHere")
|
||||
}
|
||||
|
||||
func TestErrorMessageForMalformedYAML(t *testing.T) {
|
||||
// These testcases verify behavior for the scenario described in
|
||||
// https://github.com/kubernetes-sigs/kustomize/issues/5540 .
|
||||
|
||||
testcases := map[string]struct {
|
||||
loaderNewReturnsError error
|
||||
shouldShowLoadError bool
|
||||
}{
|
||||
"shouldShowLoadError": {
|
||||
loaderNewReturnsError: utils.NewErrTimeOut(time.Second, "git init"),
|
||||
shouldShowLoadError: true,
|
||||
},
|
||||
"shouldNotShowLoadError": {
|
||||
loaderNewReturnsError: NewErrMissingKustomization("/should-fail/resources.yaml"),
|
||||
shouldShowLoadError: false,
|
||||
},
|
||||
}
|
||||
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
th.WriteF("/should-fail/kustomization.yaml", `resources:
|
||||
- resources.yaml
|
||||
`)
|
||||
th.WriteF("/should-fail/resources.yaml", `<!DOCTYPE html>
|
||||
<html class="html-devise-layout ui-light-gray" lang="en">
|
||||
<head prefix="og: http://ogp.me/ns#">
|
||||
<meta charset="utf-8">
|
||||
`)
|
||||
|
||||
for name, tc := range testcases {
|
||||
t.Run(name, func(subT *testing.T) {
|
||||
ldrWrapper := func(baseLoader ifc.Loader) ifc.Loader {
|
||||
return loaderNewThrowsError{
|
||||
baseLoader: baseLoader,
|
||||
newReturnsError: tc.loaderNewReturnsError,
|
||||
}
|
||||
}
|
||||
_, err := makeAndLoadKustTargetWithLoaderOverride(t, th.GetFSys(), "/should-fail", ldrWrapper).AccumulateTarget()
|
||||
require.Error(t, err)
|
||||
errString := err.Error()
|
||||
assert.Contains(t, errString, "accumulating resources from 'resources.yaml'")
|
||||
assert.Contains(t, errString, "MalformedYAMLError: yaml: line 3: mapping values are not allowed in this context")
|
||||
if tc.shouldShowLoadError {
|
||||
assert.Regexp(t, `hit \w+ timeout running '`, errString)
|
||||
} else {
|
||||
assert.NotRegexp(t, `hit \w+ timeout running '`, errString)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// loaderNewReturnsError duplicates baseLoader's behavior except
|
||||
// that New() returns the specified error.
|
||||
type loaderNewThrowsError struct {
|
||||
baseLoader ifc.Loader
|
||||
newReturnsError error
|
||||
}
|
||||
|
||||
func (l loaderNewThrowsError) Repo() string {
|
||||
return l.baseLoader.Repo()
|
||||
}
|
||||
|
||||
func (l loaderNewThrowsError) Root() string {
|
||||
return l.baseLoader.Root()
|
||||
}
|
||||
|
||||
func (l loaderNewThrowsError) New(_ string) (ifc.Loader, error) {
|
||||
return nil, l.newReturnsError
|
||||
}
|
||||
|
||||
func (l loaderNewThrowsError) Load(location string) ([]byte, error) {
|
||||
return l.baseLoader.Load(location) //nolint:wrapcheck // baseLoader's error is sufficient
|
||||
}
|
||||
|
||||
func (l loaderNewThrowsError) Cleanup() error {
|
||||
return l.baseLoader.Cleanup() //nolint:wrapcheck // baseLoader's error is sufficient
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@ package target_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
fLdr "sigs.k8s.io/kustomize/api/internal/loader"
|
||||
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
||||
"sigs.k8s.io/kustomize/api/internal/target"
|
||||
fLdr "sigs.k8s.io/kustomize/api/loader"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
||||
@@ -21,11 +22,7 @@ func makeAndLoadKustTarget(
|
||||
fSys filesys.FileSystem,
|
||||
root string) *target.KustTarget {
|
||||
t.Helper()
|
||||
kt := makeKustTargetWithRf(t, fSys, root, provider.NewDefaultDepProvider())
|
||||
if err := kt.Load(); err != nil {
|
||||
t.Fatalf("Unexpected load error %v", err)
|
||||
}
|
||||
return kt
|
||||
return makeAndLoadKustTargetWithLoaderOverride(t, fSys, root, nil)
|
||||
}
|
||||
|
||||
func makeKustTargetWithRf(
|
||||
@@ -34,10 +31,37 @@ func makeKustTargetWithRf(
|
||||
root string,
|
||||
pvd *provider.DepProvider) *target.KustTarget {
|
||||
t.Helper()
|
||||
ldr, err := fLdr.NewLoader(fLdr.RestrictionRootOnly, root, fSys)
|
||||
return makeKustTargetWithRfAndLoaderOverride(t, fSys, root, pvd, nil)
|
||||
}
|
||||
|
||||
func makeAndLoadKustTargetWithLoaderOverride(
|
||||
t *testing.T,
|
||||
fSys filesys.FileSystem,
|
||||
root string,
|
||||
ldrWrapperFn func(ifc.Loader) ifc.Loader) *target.KustTarget {
|
||||
t.Helper()
|
||||
kt := makeKustTargetWithRfAndLoaderOverride(t, fSys, root, provider.NewDefaultDepProvider(), ldrWrapperFn)
|
||||
if err := kt.Load(); err != nil {
|
||||
t.Fatalf("Unexpected load error %v", err)
|
||||
}
|
||||
return kt
|
||||
}
|
||||
|
||||
func makeKustTargetWithRfAndLoaderOverride(
|
||||
t *testing.T,
|
||||
fSys filesys.FileSystem,
|
||||
root string,
|
||||
pvd *provider.DepProvider,
|
||||
ldrWrapperFn func(ifc.Loader) ifc.Loader) *target.KustTarget {
|
||||
t.Helper()
|
||||
baseLoader, err := fLdr.NewLoader(fLdr.RestrictionRootOnly, root, fSys)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ldr := baseLoader
|
||||
if ldrWrapperFn != nil {
|
||||
ldr = ldrWrapperFn(baseLoader)
|
||||
}
|
||||
rf := resmap.NewFactory(pvd.GetResourceFactory())
|
||||
pc := types.DisabledPluginConfig()
|
||||
return target.NewKustTarget(
|
||||
|
||||
@@ -15,11 +15,11 @@ type errTimeOut struct {
|
||||
cmd string
|
||||
}
|
||||
|
||||
func NewErrTimeOut(d time.Duration, c string) errTimeOut {
|
||||
return errTimeOut{duration: d, cmd: c}
|
||||
func NewErrTimeOut(d time.Duration, c string) *errTimeOut {
|
||||
return &errTimeOut{duration: d, cmd: c}
|
||||
}
|
||||
|
||||
func (e errTimeOut) Error() string {
|
||||
func (e *errTimeOut) Error() string {
|
||||
return fmt.Sprintf("hit %s timeout running '%s'", e.duration, e.cmd)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
// TimedCall runs fn, failing if it doesn't complete in the given duration.
|
||||
// The description is used in the timeout error message.
|
||||
func TimedCall(description string, d time.Duration, fn func() error) error {
|
||||
done := make(chan error)
|
||||
done := make(chan error, 1)
|
||||
timer := time.NewTimer(d)
|
||||
defer timer.Stop()
|
||||
go func() { done <- fn() }()
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/goleak"
|
||||
. "sigs.k8s.io/kustomize/api/internal/utils"
|
||||
)
|
||||
|
||||
@@ -62,3 +63,20 @@ func TestTimedCallSlowWithError(t *testing.T) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimedCallGoroutineLeak(t *testing.T) {
|
||||
defer goleak.VerifyNone(t)
|
||||
err := TimedCall("function done, no goroutine leaks", timeToWait, func() error {
|
||||
time.Sleep(tooSlow)
|
||||
return fmt.Errorf("function done")
|
||||
})
|
||||
if assert.Error(t, err) {
|
||||
assert.EqualError(t, err, errMsg("function done, no goroutine leaks"))
|
||||
} else {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// The code introduces a 2-second sleep to allow the goroutine to complete its execution.
|
||||
// Subsequently, it verifies if the goroutine created by the function exits as expected.
|
||||
time.Sleep(tooSlow)
|
||||
}
|
||||
|
||||
@@ -4,15 +4,33 @@
|
||||
package krusty_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
. "sigs.k8s.io/kustomize/api/internal/target"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/krusty"
|
||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||
)
|
||||
|
||||
const validResource = `
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myService
|
||||
spec:
|
||||
selector:
|
||||
backend: bungie
|
||||
ports:
|
||||
- port: 7002
|
||||
`
|
||||
|
||||
func TestTargetMustHaveKustomizationFile(t *testing.T) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
th.WriteF("service.yaml", `
|
||||
@@ -59,17 +77,7 @@ func TestBaseMustHaveKustomizationFile(t *testing.T) {
|
||||
resources:
|
||||
- base
|
||||
`)
|
||||
th.WriteF("base/service.yaml", `
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myService
|
||||
spec:
|
||||
selector:
|
||||
backend: bungie
|
||||
ports:
|
||||
- port: 7002
|
||||
`)
|
||||
th.WriteF("base/service.yaml", validResource)
|
||||
err := th.RunWithErr(".", th.MakeDefaultOptions())
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error")
|
||||
@@ -160,3 +168,175 @@ spec:
|
||||
secretName: cert-tls
|
||||
`)
|
||||
}
|
||||
|
||||
func TestAccumulateResourcesErrors(t *testing.T) {
|
||||
type testcase struct {
|
||||
name string
|
||||
resource string
|
||||
// resourceFunc generates a resource string using the URL to the local
|
||||
// test server (optional).
|
||||
resourceFunc func(string) string
|
||||
// resourceServerSetup configures the local test server (optional).
|
||||
resourceServerSetup func(*http.ServeMux)
|
||||
isAbsolute bool
|
||||
files map[string]string
|
||||
// errFile, errDir are regex for the expected error message output
|
||||
// when kustomize tries to accumulate resource as file and dir,
|
||||
// respectively. The test substitutes occurrences of "%s" in the
|
||||
// error strings with the absolute path where kustomize looks for it.
|
||||
errFile, errDir string
|
||||
}
|
||||
populateAbsolutePaths := func(tc testcase, dir string) testcase {
|
||||
filePaths := make(map[string]string, len(tc.files)+1)
|
||||
for file, content := range tc.files {
|
||||
filePaths[filepath.Join(dir, file)] = content
|
||||
}
|
||||
resourcePath := filepath.Join(dir, tc.resource)
|
||||
if tc.isAbsolute {
|
||||
tc.resource = resourcePath
|
||||
}
|
||||
filePaths[filepath.Join(dir, "kustomization.yaml")] = fmt.Sprintf(`
|
||||
resources:
|
||||
- %s
|
||||
`, tc.resource)
|
||||
tc.files = filePaths
|
||||
regPath := regexp.QuoteMeta(resourcePath)
|
||||
tc.errFile = strings.ReplaceAll(tc.errFile, "%s", regPath)
|
||||
tc.errDir = strings.ReplaceAll(tc.errDir, "%s", regPath)
|
||||
return tc
|
||||
}
|
||||
buildError := func(tc testcase) string {
|
||||
const (
|
||||
prefix = "accumulating resources"
|
||||
filePrefixf = "accumulating resources from '%s'"
|
||||
fileWrapperIfDirf = "accumulation err='%s'"
|
||||
separator = ": "
|
||||
)
|
||||
parts := []string{
|
||||
prefix,
|
||||
strings.Join([]string{
|
||||
fmt.Sprintf(filePrefixf, regexp.QuoteMeta(tc.resource)),
|
||||
tc.errFile,
|
||||
}, separator),
|
||||
}
|
||||
if tc.errDir != "" {
|
||||
parts[1] = fmt.Sprintf(fileWrapperIfDirf, parts[1])
|
||||
parts = append(parts, tc.errDir)
|
||||
}
|
||||
return strings.Join(parts, separator)
|
||||
}
|
||||
for _, test := range []testcase{
|
||||
{
|
||||
name: "remote file not considered repo",
|
||||
resourceFunc: func(url string) string {
|
||||
return fmt.Sprintf("%s/segments-too-few-to-be-repo", url)
|
||||
},
|
||||
resourceServerSetup: func(server *http.ServeMux) {
|
||||
server.HandleFunc("/", func(out http.ResponseWriter, req *http.Request) {
|
||||
out.WriteHeader(http.StatusNotFound)
|
||||
})
|
||||
},
|
||||
// It's acceptable for the error output of a remote file-like
|
||||
// resource to not indicate the resource's status as a
|
||||
// local directory. Though it is possible for a remote file-like
|
||||
// resource to be a local directory, it is very unlikely.
|
||||
errFile: `HTTP Error: status code 404 \(Not Found\)\z`,
|
||||
},
|
||||
{
|
||||
name: "remote file qualifies as repo",
|
||||
resourceFunc: func(url string) string {
|
||||
return fmt.Sprintf("%s/long/enough/to/have/org/and/repo", url)
|
||||
},
|
||||
resourceServerSetup: func(server *http.ServeMux) {
|
||||
server.HandleFunc("/", func(out http.ResponseWriter, req *http.Request) {
|
||||
out.WriteHeader(http.StatusInternalServerError)
|
||||
})
|
||||
},
|
||||
// TODO(4788): This error message is technically wrong. Just
|
||||
// because we fail to GET a resource does not mean the resource is
|
||||
// not a remote file. We should return the GET status code as well.
|
||||
errFile: "URL is a git repository",
|
||||
errDir: `failed to run \S+/git fetch --depth=1 .+`,
|
||||
},
|
||||
{
|
||||
name: "local file qualifies as repo",
|
||||
// The .example top level domain is reserved for example purposes,
|
||||
// see RFC 2606.
|
||||
resource: "package@v1.28.0.example/configs/base",
|
||||
errFile: `evalsymlink failure on '%s' .+`,
|
||||
errDir: `failed to run \S+/git fetch --depth=1 .+`,
|
||||
},
|
||||
{
|
||||
name: "relative path does not exist",
|
||||
resource: "file-or-directory",
|
||||
errFile: `evalsymlink failure on '%s' .+`,
|
||||
errDir: `must build at directory: not a valid directory: evalsymlink failure .+`,
|
||||
},
|
||||
{
|
||||
name: "absolute path does not exist",
|
||||
resource: "file-or-directory",
|
||||
isAbsolute: true,
|
||||
errFile: `evalsymlink failure on '%s' .+`,
|
||||
errDir: `new root '%s' cannot be absolute`,
|
||||
},
|
||||
{
|
||||
name: "relative file violates restrictions",
|
||||
resource: "../base/resource.yaml",
|
||||
files: map[string]string{
|
||||
"../base/resource.yaml": validResource,
|
||||
},
|
||||
errFile: "security; file '%s' is not in or below .+",
|
||||
// TODO(4348): Over-inclusion of directory error message when we
|
||||
// know resource is file.
|
||||
errDir: "must build at directory: '%s': file is not directory",
|
||||
},
|
||||
{
|
||||
name: "absolute file violates restrictions",
|
||||
resource: "../base/resource.yaml",
|
||||
isAbsolute: true,
|
||||
files: map[string]string{
|
||||
"../base/resource.yaml": validResource,
|
||||
},
|
||||
errFile: "security; file '%s' is not in or below .+",
|
||||
// TODO(4348): Over-inclusion of directory error message when we
|
||||
// know resource is file.
|
||||
errDir: `new root '%s' cannot be absolute`,
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if test.resourceFunc != nil {
|
||||
// Configure test server handler
|
||||
handler := http.NewServeMux()
|
||||
if test.resourceServerSetup != nil {
|
||||
test.resourceServerSetup(handler)
|
||||
}
|
||||
// Start test server
|
||||
svr := httptest.NewServer(handler)
|
||||
defer svr.Close()
|
||||
// Generate resource with test server address
|
||||
test.resource = test.resourceFunc(svr.URL)
|
||||
}
|
||||
|
||||
// Should use real file system to indicate that we are creating
|
||||
// new temporary directories on disk when we attempt to fetch repos.
|
||||
fs, tmpDir := kusttest_test.Setup(t)
|
||||
root := tmpDir.Join("root")
|
||||
require.NoError(t, fs.Mkdir(root))
|
||||
|
||||
test = populateAbsolutePaths(test, root)
|
||||
for file, content := range test.files {
|
||||
dir := filepath.Dir(file)
|
||||
require.NoError(t, fs.MkdirAll(dir))
|
||||
require.NoError(t, fs.WriteFile(file, []byte(content)))
|
||||
}
|
||||
|
||||
b := krusty.MakeKustomizer(krusty.MakeDefaultOptions())
|
||||
_, err := b.Run(fs, root)
|
||||
require.Regexp(t, buildError(test), err.Error())
|
||||
})
|
||||
}
|
||||
// TODO(annasong): add tests that check accumulateResources errors for
|
||||
// - repos
|
||||
// - local directories
|
||||
// - files that yield malformed yaml errors
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/internal/loader"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/loader"
|
||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||
)
|
||||
|
||||
@@ -39,7 +39,7 @@ resources:
|
||||
- deploy.yaml
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
literals:
|
||||
literals:
|
||||
- testValue=purple
|
||||
- otherValue=green
|
||||
`)
|
||||
@@ -64,7 +64,7 @@ resources:
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
behavior: merge
|
||||
literals:
|
||||
literals:
|
||||
- testValue=blue
|
||||
- compValue=red
|
||||
`)
|
||||
@@ -154,7 +154,7 @@ spec:
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
behavior: merge
|
||||
literals:
|
||||
literals:
|
||||
- otherValue=orange
|
||||
`),
|
||||
writeK("prod", `
|
||||
@@ -319,7 +319,7 @@ resources:
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
behavior: merge
|
||||
literals:
|
||||
literals:
|
||||
- compValue=red
|
||||
- testValue=blue
|
||||
`),
|
||||
@@ -350,7 +350,7 @@ kind: Component
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
behavior: merge
|
||||
literals:
|
||||
literals:
|
||||
- otherValue=orange
|
||||
`),
|
||||
},
|
||||
@@ -562,7 +562,7 @@ kind: Component
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
behavior: merge
|
||||
literals:
|
||||
literals:
|
||||
- otherValue=orange
|
||||
`),
|
||||
},
|
||||
@@ -657,3 +657,113 @@ components:
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderOfAccumulatedComponent(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
input []FileGen
|
||||
expectedOutput string
|
||||
}{
|
||||
"components_using_a_generated_resource_by_configMapGenerator": {
|
||||
input: []FileGen{
|
||||
writeK("", `
|
||||
resources:
|
||||
- resource.yaml
|
||||
components:
|
||||
- components
|
||||
configMapGenerator:
|
||||
- name: generated-resource
|
||||
literals:
|
||||
- key=value
|
||||
options:
|
||||
disableNameSuffixHash: true`),
|
||||
writeF("resource.yaml", `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: config-from-resources
|
||||
data:
|
||||
foo: bar`),
|
||||
writeC("/components", `
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||
kind: Component
|
||||
nameSuffix: -suffix
|
||||
`),
|
||||
},
|
||||
expectedOutput: `
|
||||
apiVersion: v1
|
||||
data:
|
||||
foo: bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: config-from-resources-suffix
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
key: value
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: generated-resource-suffix
|
||||
`},
|
||||
"components_are_applied_before_replacements_transformer_applied": {
|
||||
input: []FileGen{
|
||||
writeK("", `
|
||||
resources:
|
||||
- resource.yaml
|
||||
components:
|
||||
- components
|
||||
replacements:
|
||||
- source:
|
||||
kind: Pod
|
||||
name: myapp-pod
|
||||
fieldPath: metadata.namespace
|
||||
targets:
|
||||
- select:
|
||||
kind: Pod
|
||||
name: myapp-pod
|
||||
fieldPaths:
|
||||
- spec.containers.[name=myapp-container].env.[name=CURRENT_POD_NAMESPACE].value`),
|
||||
writeF("resource.yaml", `
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
namespace: dev-assa
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: myapp-container
|
||||
env:
|
||||
- name: CURRENT_POD_NAMESPACE
|
||||
value: "$(PLACEHOLDER)"`),
|
||||
writeC("/components", `
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||
kind: Component
|
||||
namespace: kustomize-namespace`),
|
||||
},
|
||||
expectedOutput: `
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
namespace: kustomize-namespace
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: CURRENT_POD_NAMESPACE
|
||||
value: kustomize-namespace
|
||||
image: busybox
|
||||
name: myapp-container
|
||||
`},
|
||||
}
|
||||
|
||||
for testName, test := range tests {
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
for _, f := range test.input {
|
||||
f(th)
|
||||
}
|
||||
m := th.Run(".", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, test.expectedOutput)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ package krusty_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||
)
|
||||
|
||||
@@ -229,6 +228,9 @@ type: Opaque
|
||||
`)
|
||||
}
|
||||
|
||||
// TODO: This should be an error instead. However, we can't strict unmarshal until we have a yaml
|
||||
// lib that support case-insensitive keys and anchors.
|
||||
// See https://github.com/kubernetes-sigs/kustomize/issues/5061
|
||||
func TestGeneratorRepeatsInKustomization(t *testing.T) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
th.WriteK(".", `
|
||||
@@ -261,13 +263,24 @@ krypton
|
||||
xenon
|
||||
radon
|
||||
`)
|
||||
err := th.RunWithErr(".", th.MakeDefaultOptions())
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error")
|
||||
}
|
||||
assert.Contains(t, err.Error(),
|
||||
"invalid Kustomization: error converting YAML to JSON: yaml: unmarshal errors:\n"+
|
||||
" line 13: key \"literals\" already set in map\n line 18: key \"files\" already set in map")
|
||||
m := th.Run(".", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, `
|
||||
apiVersion: v1
|
||||
data:
|
||||
fruit: apple
|
||||
nobles: |2
|
||||
|
||||
helium
|
||||
neon
|
||||
argon
|
||||
krypton
|
||||
xenon
|
||||
radon
|
||||
vegetable: broccoli
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: blah-bob-db529cg5bk
|
||||
`)
|
||||
}
|
||||
|
||||
func TestIssue3393(t *testing.T) {
|
||||
@@ -558,3 +571,204 @@ metadata:
|
||||
name: test-k9cc55dfm5
|
||||
`)
|
||||
}
|
||||
|
||||
func TestDataIsSingleQuote(t *testing.T) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
th.WriteK(".", `
|
||||
configMapGenerator:
|
||||
- name: test
|
||||
literals:
|
||||
- TEST='
|
||||
`)
|
||||
|
||||
m := th.Run(".", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(
|
||||
m, `apiVersion: v1
|
||||
data:
|
||||
TEST: ''''
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-m8t7bmb6g2
|
||||
`)
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/kubernetes-sigs/kustomize/issues/5047
|
||||
func TestPrefixSuffix(t *testing.T) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
th.WriteF("kustomization.yaml", `
|
||||
resources:
|
||||
- a
|
||||
- b
|
||||
`)
|
||||
|
||||
th.WriteF("a/kustomization.yaml", `
|
||||
resources:
|
||||
- ../common
|
||||
|
||||
namePrefix: a
|
||||
`)
|
||||
|
||||
th.WriteF("b/kustomization.yaml", `
|
||||
resources:
|
||||
- ../common
|
||||
|
||||
namePrefix: b
|
||||
`)
|
||||
|
||||
th.WriteF("common/kustomization.yaml", `
|
||||
resources:
|
||||
- service
|
||||
|
||||
configMapGenerator:
|
||||
- name: "-example-configmap"
|
||||
`)
|
||||
|
||||
th.WriteF("common/service/deployment.yaml", `
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
|
||||
metadata:
|
||||
name: "-"
|
||||
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: "-example-configmap"
|
||||
`)
|
||||
|
||||
th.WriteF("common/service/kustomization.yaml", `
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
nameSuffix: api
|
||||
`)
|
||||
|
||||
m := th.Run(".", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: a-api
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- envFrom:
|
||||
- configMapRef:
|
||||
name: a-example-configmap-6ct58987ht
|
||||
name: app
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: a-example-configmap-6ct58987ht
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: b-api
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- envFrom:
|
||||
- configMapRef:
|
||||
name: b-example-configmap-6ct58987ht
|
||||
name: app
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: b-example-configmap-6ct58987ht
|
||||
`)
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/kubernetes-sigs/kustomize/issues/5047
|
||||
func TestPrefixSuffix2(t *testing.T) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
th.WriteF("kustomization.yaml", `
|
||||
resources:
|
||||
- a
|
||||
- b
|
||||
`)
|
||||
|
||||
th.WriteF("a/kustomization.yaml", `
|
||||
resources:
|
||||
- ../common
|
||||
|
||||
namePrefix: a
|
||||
`)
|
||||
|
||||
th.WriteF("b/kustomization.yaml", `
|
||||
resources:
|
||||
- ../common
|
||||
|
||||
namePrefix: b
|
||||
`)
|
||||
|
||||
th.WriteF("common/deployment.yaml", `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: "-example"
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: "-example-configmap"
|
||||
`)
|
||||
|
||||
th.WriteF("common/kustomization.yaml", `
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
configMapGenerator:
|
||||
- name: "-example-configmap"
|
||||
`)
|
||||
|
||||
m := th.Run(".", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: a-example
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- envFrom:
|
||||
- configMapRef:
|
||||
name: a-example-configmap-6ct58987ht
|
||||
name: app
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: a-example-configmap-6ct58987ht
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: b-example
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- envFrom:
|
||||
- configMapRef:
|
||||
name: b-example-configmap-6ct58987ht
|
||||
name: app
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: b-example-configmap-6ct58987ht
|
||||
`)
|
||||
}
|
||||
|
||||
@@ -17,12 +17,16 @@ commonLabels:
|
||||
vars:
|
||||
- name: APRIL_DIET
|
||||
objref:
|
||||
group: foo
|
||||
version: v1
|
||||
kind: Giraffe
|
||||
name: april
|
||||
fieldref:
|
||||
fieldpath: spec.diet
|
||||
- name: KOKO_DIET
|
||||
objref:
|
||||
group: foo
|
||||
version: v1
|
||||
kind: Gorilla
|
||||
name: koko
|
||||
fieldref:
|
||||
@@ -36,6 +40,7 @@ configurations:
|
||||
- config/custom.yaml
|
||||
`)
|
||||
th.WriteF("base/giraffes.yaml", `
|
||||
apiVersion: foo/v1
|
||||
kind: Giraffe
|
||||
metadata:
|
||||
name: april
|
||||
@@ -43,6 +48,7 @@ spec:
|
||||
diet: mimosa
|
||||
location: NE
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Giraffe
|
||||
metadata:
|
||||
name: may
|
||||
@@ -51,6 +57,7 @@ spec:
|
||||
location: SE
|
||||
`)
|
||||
th.WriteF("base/gorilla.yaml", `
|
||||
apiVersion: foo/v1
|
||||
kind: Gorilla
|
||||
metadata:
|
||||
name: koko
|
||||
@@ -59,7 +66,7 @@ spec:
|
||||
location: SW
|
||||
`)
|
||||
th.WriteF("base/animalPark.yaml", `
|
||||
apiVersion: foo
|
||||
apiVersion: foo/v1
|
||||
kind: AnimalPark
|
||||
metadata:
|
||||
name: sandiego
|
||||
@@ -94,7 +101,7 @@ varReference:
|
||||
`)
|
||||
m := th.Run("base", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, `
|
||||
apiVersion: foo
|
||||
apiVersion: foo/v1
|
||||
kind: AnimalPark
|
||||
metadata:
|
||||
labels:
|
||||
@@ -109,6 +116,7 @@ spec:
|
||||
gorillaRef:
|
||||
name: x-koko
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Giraffe
|
||||
metadata:
|
||||
labels:
|
||||
@@ -118,6 +126,7 @@ spec:
|
||||
diet: mimosa
|
||||
location: NE
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Giraffe
|
||||
metadata:
|
||||
labels:
|
||||
@@ -127,6 +136,7 @@ spec:
|
||||
diet: acacia
|
||||
location: SE
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Gorilla
|
||||
metadata:
|
||||
labels:
|
||||
@@ -163,7 +173,7 @@ varReference:
|
||||
`)
|
||||
m := th.Run("base", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, `
|
||||
apiVersion: foo
|
||||
apiVersion: foo/v1
|
||||
kind: AnimalPark
|
||||
metadata:
|
||||
labels:
|
||||
@@ -178,6 +188,7 @@ spec:
|
||||
gorillaRef:
|
||||
name: x-koko
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Giraffe
|
||||
metadata:
|
||||
labels:
|
||||
@@ -187,6 +198,7 @@ spec:
|
||||
diet: mimosa
|
||||
location: NE
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Giraffe
|
||||
metadata:
|
||||
labels:
|
||||
@@ -196,6 +208,7 @@ spec:
|
||||
diet: acacia
|
||||
location: SE
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Gorilla
|
||||
metadata:
|
||||
labels:
|
||||
@@ -215,17 +228,20 @@ func TestFixedBug605_BaseCustomizationAvailableInOverlay(t *testing.T) {
|
||||
nameReference:
|
||||
- kind: Gorilla
|
||||
fieldSpecs:
|
||||
- apiVersion: foo
|
||||
- group: foo
|
||||
version: v1
|
||||
kind: AnimalPark
|
||||
path: spec/gorillaRef/name
|
||||
- kind: Giraffe
|
||||
fieldSpecs:
|
||||
- apiVersion: foo
|
||||
- group: foo
|
||||
version: v1
|
||||
kind: AnimalPark
|
||||
path: spec/giraffeRef/name
|
||||
varReference:
|
||||
- path: spec/food
|
||||
apiVersion: foo
|
||||
group: foo
|
||||
version: v1
|
||||
kind: AnimalPark
|
||||
`)
|
||||
th.WriteK("overlay", `
|
||||
@@ -239,6 +255,7 @@ resources:
|
||||
- ursus.yaml
|
||||
`)
|
||||
th.WriteF("overlay/ursus.yaml", `
|
||||
apiVersion: foo/v1
|
||||
kind: Gorilla
|
||||
metadata:
|
||||
name: ursus
|
||||
@@ -248,7 +265,7 @@ spec:
|
||||
`)
|
||||
// The following replaces the gorillaRef in the AnimalPark.
|
||||
th.WriteF("overlay/animalPark.yaml", `
|
||||
apiVersion: foo
|
||||
apiVersion: foo/v1
|
||||
kind: AnimalPark
|
||||
metadata:
|
||||
name: sandiego
|
||||
@@ -258,7 +275,7 @@ spec:
|
||||
`)
|
||||
m := th.Run("overlay", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, `
|
||||
apiVersion: foo
|
||||
apiVersion: foo/v1
|
||||
kind: AnimalPark
|
||||
metadata:
|
||||
labels:
|
||||
@@ -274,6 +291,7 @@ spec:
|
||||
gorillaRef:
|
||||
name: o-ursus
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Giraffe
|
||||
metadata:
|
||||
labels:
|
||||
@@ -284,6 +302,7 @@ spec:
|
||||
diet: mimosa
|
||||
location: NE
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Giraffe
|
||||
metadata:
|
||||
labels:
|
||||
@@ -294,6 +313,7 @@ spec:
|
||||
diet: acacia
|
||||
location: SE
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Gorilla
|
||||
metadata:
|
||||
labels:
|
||||
@@ -304,6 +324,7 @@ spec:
|
||||
diet: bambooshoots
|
||||
location: SW
|
||||
---
|
||||
apiVersion: foo/v1
|
||||
kind: Gorilla
|
||||
metadata:
|
||||
labels:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user