Compare commits

...

169 Commits

Author SHA1 Message Date
Jeff Regan
0e251ed96e Update README.md 2019-12-11 15:22:30 -08:00
Jeff Regan
6b7236a206 Update INSTALL.md 2019-12-11 14:26:09 -08:00
Kubernetes Prow Robot
f65cac96d6 Merge pull request #1932 from haiyanmeng/fix
Avoid processing the nil pointer returned by kustomizationResultAdapter
2019-12-11 14:22:32 -08:00
Haiyan Meng
0d79219e46 Avoid processing the nil pointer returned by kustomizationResultAdapter
Currently, the crawler job panics whenever a nil pointer is returned by
kustomizationResultAdapter.
2019-12-11 13:54:01 -08:00
Kubernetes Prow Robot
e4635b456a Merge pull request #1930 from mortent/statusCli
cli for status
2019-12-11 13:34:32 -08:00
Morten Torkildsen
1b3b8522f9 cli for status 2019-12-11 13:13:09 -08:00
Jeff Regan
4098d6fdfb Merge pull request #1928 from haiyanmeng/empty
Mulitple improvements of the crawler
2019-12-11 13:04:29 -08:00
Jeff Regan
4ba69b27f8 Merge pull request #1922 from bzub/cmd_config_docs
cmd/config: Documentation nits + updates.
2019-12-11 12:59:41 -08:00
Haiyan Meng
bffc0d7071 Mulitple improvements of the crawler
1) Set document IDs to avoid duplicating documents;
2) Set the `creationTime` field of each document in the index;
3) set the `values`, `kinds` and `identifiers` fields for all documents;
4) Add a `Copy` method into the `Document` struct: this fixes the issue
where all the documents existing in the index point to the same Document
object;
5) Avoid using keystore redis;
6) Set imagePullPolicy to `Always` for crawler jobs.
2019-12-11 11:10:48 -08:00
Jeff Regan
54b1549586 Merge pull request #1909 from bzub/1908-plugin_test_path
Detect path to plugins from krusty tests.
2019-12-11 10:24:14 -08:00
bzub
3803541bfd Remove extraneous whitespace.
make all (generate docs)

Update examples in cmd docs.

make all (generate docs)

functions/examples: Whitespace cleanup.

functions/examples: Fix some example commands.
2019-12-11 12:12:32 -06:00
Kubernetes Prow Robot
2102ddab7c Merge pull request #1916 from bzub/plugins_doc_go_link
Update plugins/doc.go link.
2019-12-10 15:50:06 -08:00
Kubernetes Prow Robot
f186a0d6bb Merge pull request #1927 from frankfarzan/config_io_docs
Expand and format Configuration IO API Semantics.
2019-12-10 13:24:05 -08:00
Frank Farzan
b0f1f66d9a Document the default value 2019-12-10 12:27:02 -08:00
Frank Farzan
8c037ba109 Index is a number not a string 2019-12-10 12:15:28 -08:00
Frank Farzan
5e5e3b19f5 Expand and format Configuration IO API Semantics. 2019-12-10 12:02:49 -08:00
Kubernetes Prow Robot
ad94f2c0eb Merge pull request #1921 from pwittrock/fixes
kyaml: fix error handling
2019-12-09 17:07:30 -08:00
Phillip Wittrock
b333115314 kyaml: fix error handling 2019-12-09 16:38:56 -08:00
Kubernetes Prow Robot
50c9916eae Merge pull request #1905 from pwittrock/autocomplete
shell completion for kustomize commands
2019-12-09 16:37:30 -08:00
Kubernetes Prow Robot
8d72bf6e5c Merge pull request #1917 from frankfarzan/fix_run
Fix 'config run' by removing default mount.
2019-12-09 15:04:40 -08:00
Frank Farzan
a4c69d9cde Fix 'config run' by removing default mount.
In, pull #1822 mount logic was refactored where the default
mount using zero-value no longer makes sense and leads to
this failure:

"invalid argument "type=,src=,dst=:ro" for "--mount" flag: type is
required"

I think the intent here was to remove default mount.
2019-12-09 14:37:57 -08:00
bzub
ecb9b9efa4 Update plugins/doc.go link. 2019-12-09 15:45:05 -06:00
Phillip Wittrock
2eacbeaa87 shell completion for kustomize commands 2019-12-09 09:22:14 -08:00
Kubernetes Prow Robot
46be801a48 Merge pull request #1910 from artmello/enable_goconst
kyaml: Enable goconst Go Linter
2019-12-09 08:40:02 -08:00
Arthur Mello
0bace652c3 Move repeated variable content to constants following linter suggestion 2019-12-08 07:12:48 -03:00
Arthur Mello
f0779cd02f kyaml: Enable goconst Go Linter 2019-12-07 16:27:25 -03:00
bzub
105a8e57c8 Detect path to plugins from krusty tests. 2019-12-07 13:16:15 -06:00
Kubernetes Prow Robot
3703450931 Merge pull request #1893 from artmello/enable_linters
kyaml: Enable Go linters (lll, stylecheck, unparam, whitespace)
2019-12-06 08:32:50 -08:00
Arthur Mello
d4fa006ccb Remove leading/trailing newlines following whitespace linter recommendation 2019-12-05 23:49:00 -03:00
Jeff Regan
b2814c5310 Update INSTALL.md 2019-12-05 18:22:37 -08:00
Jeff Regan
c00cf120ff Update INSTALL.md 2019-12-05 18:22:23 -08:00
Jeff Regan
decca7fcd3 Merge pull request #1891 from mortent/FixControllerRuntimeDeps
Fix dependencies for kstatus
2019-12-05 18:17:31 -08:00
Kubernetes Prow Robot
9914017f60 Merge pull request #1897 from pwittrock/workspace
support writing run output to files
2019-12-05 18:08:49 -08:00
Arthur Mello
a077482e99 Rename struct field to solve issue raised by go vet 2019-12-05 23:06:19 -03:00
Arthur Mello
849e0f357a Unname unused parameters following unparam linter recommendation 2019-12-05 22:50:37 -03:00
Arthur Mello
df7688002a Remove init function following gochecknoinits linter recommendation 2019-12-05 22:44:14 -03:00
Arthur Mello
e811da14d8 Rename variable, constants and struct fields following stylecheck linter recommendation 2019-12-05 22:39:29 -03:00
Phillip Wittrock
9e5af98a94 support writing run output to files
so that it isn't necessary to wrap in bash to redirect to a file
2019-12-05 17:25:01 -08:00
Arthur Mello
f2c7066088 Remove leading/trailing newlines following whitespace linter recommendation 2019-12-05 22:23:35 -03:00
Jeff Regan
3f5dc1e80a Merge pull request #1896 from monopole/tweakInstall
Improve install script error message
2019-12-05 15:18:42 -08:00
Jeffrey Regan
04bfb3e94d Tweak install. 2019-12-05 15:17:33 -08:00
Jeff Regan
567bc834c9 Update INSTALL.md 2019-12-05 14:47:11 -08:00
Jeff Regan
49f8b2bee8 Update INSTALL.md 2019-12-05 14:43:58 -08:00
Jeff Regan
b710a76818 Add kustomize install script. 2019-12-05 14:02:16 -08:00
Jeff Regan
823c59666b Merge pull request #1894 from monopole/installScript
Kustomize installation script.
2019-12-05 13:51:53 -08:00
Jeffrey Regan
e14c441e77 Kustomize installation script. 2019-12-05 13:50:53 -08:00
Arthur Mello
de4d50386d kyaml: Enable Go linters (lll, stylecheck, unparam, whitespace) 2019-12-05 16:32:17 -03:00
Jeff Regan
969a1e8f37 Merge pull request #1892 from monopole/getRidOfFakeLoader
Get rid of the 'fake' loader.
2019-12-05 11:22:47 -08:00
Jeff Regan
184735fa89 Merge pull request #1887 from Liujingfang1/replacement-poc
add replacement type and an example transformer
2019-12-05 11:10:35 -08:00
Jeffrey Regan
caa71a73fe Get rid of the fake loader. 2019-12-05 10:50:42 -08:00
Morten Torkildsen
2625502ddb Fix dependencies for kstatus 2019-12-04 21:56:55 -08:00
Kubernetes Prow Robot
7c1b477ff6 Merge pull request #1888 from haiyanmeng/duplicates
Remove duplicates in the `kinds` field of the kustomize ElasticSearch index
2019-12-04 12:04:57 -08:00
Haiyan Meng
d25b6ff3dc Remove duplicates in kinds 2019-12-04 11:24:54 -08:00
Haiyan Meng
68a196dbe5 Add a test case to demonstrate kinds have duplicates 2019-12-04 11:24:23 -08:00
Jingfang Liu
c7600bc079 add replacement type and an example transformer 2019-12-04 11:13:05 -08:00
Jeff Regan
79884240ae Merge pull request #1883 from haiyanmeng/mapping
Set the ElasticSearch index creation configuration
2019-12-03 19:09:55 -08:00
Kubernetes Prow Robot
3880b8df1d Merge pull request #1822 from joncwong/container-local-vol
Add Local Volume support to ContainerFilter
2019-12-03 16:30:58 -08:00
Haiyan Meng
8aaa3f56f5 Set the ElasticSearch index creation configuration
Currently, the `kustomize` index in ElasticSearch is using dynamic
mapping, which sets the types of all the fields to `text`. However,
`text` field type is good for full-text value matching, and not good for
exact-value matching.  For exact-value matching, the `keyword` filed
type should be used.
2019-12-03 15:16:32 -08:00
Jeff Regan
4a7ade6421 Merge pull request #1882 from monopole/crawlerNitSweep
Fix some nits in the crawler and elsewhere.
2019-12-03 11:22:36 -08:00
Jeffrey Regan
e9ab3da164 Fix some nits in the crawler and elsewhere. 2019-12-03 10:44:44 -08:00
Jonathan Wong
dff30b926e Nit fixes and proper RunFns integration 2019-12-03 00:17:12 -08:00
Jeff Regan
fd5db20a48 Update harness.go 2019-12-02 18:47:07 -08:00
Jeff Regan
8e99dbdaf0 Merge pull request #1881 from monopole/pluginSimplification
Simplify test framework
2019-12-02 18:37:04 -08:00
Jeffrey Regan
861c86a70a Simplify plugin tests. 2019-12-02 17:12:59 -08:00
Jeff Regan
0a19a5dbd9 Merge pull request #1879 from monopole/consolidateTestHarness
Consolidate test harness to one package.
2019-12-02 12:48:15 -08:00
Jeffrey Regan
382c330f5b Consolidate test harness to one package. 2019-12-02 12:29:10 -08:00
Kubernetes Prow Robot
ce935448c1 Merge pull request #1877 from joncwong/patch-5
Fix three typos
2019-12-02 07:49:05 -08:00
Jonathan Wong
49287a0f8f Fix verb noun agreement mistake 2019-12-02 02:01:00 -08:00
Jonathan Wong
1433ea4faa Fix two typos 2019-12-02 01:55:20 -08:00
Jeff Regan
daa14ae4bd Merge pull request #1875 from lalyos/fix-sed-plugin
fix quotation issues by using a bash array
2019-12-01 07:54:07 -08:00
Jeff Regan
46af583a57 Update bugs.md 2019-12-01 07:48:10 -08:00
Jeff Regan
f33069fc15 Update bugs.md 2019-12-01 07:24:56 -08:00
lalyos
cf5d3e73c0 fix quotation issues by using a bash array
see: http://mywiki.wooledge.org/BashFAQ/050
2019-11-30 21:51:32 +01:00
Jeff Regan
4f8eaacc9b Update kustomizer_test.go 2019-11-30 11:49:40 -08:00
Jeff Regan
47d6d498d6 Merge pull request #1874 from monopole/oopsMoreTest
More tests/examples.
2019-11-30 11:34:40 -08:00
jregan
1f85ce454d More tests/examples. 2019-11-30 11:32:08 -08:00
Jeff Regan
fc8c45cff5 Merge pull request #1872 from monopole/printPluginEnvPlugin
Add PrintPluginEnv plugin.
2019-11-30 10:29:37 -08:00
jregan
d98af3f06a Add PrintPluginEnv plugin. 2019-11-30 09:58:11 -08:00
Jeff Regan
d942e6fa59 Merge pull request #1871 from monopole/moar2
Move remaining examples.
2019-11-30 08:28:53 -08:00
jregan
fdd2cc5004 Move another test. 2019-11-30 07:31:38 -08:00
Jeff Regan
59b1c81e7e Merge pull request #1870 from monopole/moar
Move more examples up.
2019-11-30 06:58:35 -08:00
jregan
ae0658869a Move more examples up. 2019-11-30 06:57:57 -08:00
Kubernetes Prow Robot
5491202d69 Merge pull request #1869 from Dingshujie/mv_test_example_to_krusty
mv /api/internal/target example to /api/krusty
2019-11-30 06:19:02 -08:00
Dingshujie
c3716ff3e0 mv diamonds to api/krusty/, Provide another high level example. 2019-11-30 17:35:09 +08:00
Dingshujie
8e7c53b9e7 mv extendedpatch_test, inlinepatch_test to api/krusty/, Provide another high level example. 2019-11-30 17:35:08 +08:00
Dingshujie
cbfe314778 mv generatormergeandreplace_test, generatoroptions_test to api/krusty/, Provide another high level example. 2019-11-30 17:35:08 +08:00
Dingshujie
2d39d64d3a mv mutiplepath_test, nullvalues_test to api/krusty/, Provide another high level example. 2019-11-30 17:35:08 +08:00
Dingshujie
cd84b65972 mv pruneconfigmap_test to api/krusty/, Provide another high level example. 2019-11-30 17:35:08 +08:00
Dingshujie
fd7574cd61 mv variableref_test to api/krusty/, Provide another high level example. 2019-11-30 17:35:08 +08:00
Dingshujie
d28ef820ea mv resourceconflict_test to api/krusty/, Provide another high level example. 2019-11-30 14:50:36 +08:00
Dingshujie
e5c314a3ea mv namespace_test to api/krusty/, Provide another high level example. 2019-11-30 14:25:02 +08:00
Dingshujie
189f65dab9 mv crd_test to api/krusty/, Provide another high level example. 2019-11-30 09:41:56 +08:00
Dingshujie
9942a9278f mv configmaps_test to api/krusty/, Provide another high level example. 2019-11-30 09:34:01 +08:00
Jeff Regan
44db041682 Merge pull request #1867 from monopole/moarTests
More tests.
2019-11-29 08:53:10 -08:00
jregan
a49a764705 More tests. 2019-11-29 08:31:51 -08:00
Jeff Regan
680a0812c6 Merge pull request #1866 from monopole/anotherTestMove
Move another test up.
2019-11-29 08:02:03 -08:00
jregan
50c63d0021 Move another test up. 2019-11-29 08:00:03 -08:00
Jeff Regan
37e167e8d1 Merge pull request #1865 from monopole/simplifyPluginTestHarness
Simplify and document plugin test harness.
2019-11-29 07:55:27 -08:00
jregan
038c070626 Simplify and document plugin test harness. 2019-11-29 07:30:42 -08:00
Jeff Regan
8bb8637213 Update replicas.md 2019-11-29 07:00:23 -08:00
Jeff Regan
7ae21cb933 Merge pull request #1864 from Dingshujie/master
mv basereusenameprefix_test to api/krusty/
2019-11-29 06:55:42 -08:00
Jeff Regan
8fb64ffb0c Merge pull request #1863 from lundbird/patch-1
Add example for replicas in kustomization.yaml
2019-11-29 05:07:51 -08:00
Jeff Regan
f5a7227e26 Merge pull request #1859 from utilitywarehouse/master
Fallback to full clone if git fetch fails
2019-11-29 05:05:30 -08:00
Dingshujie
8a2b3cd1d9 mv basereusenameprefix_test to api/krusty/, Provide another high level example. 2019-11-29 20:42:56 +08:00
john
61133f3e2e remove flag logic 2019-11-29 08:58:14 +00:00
john
bf339173c8 unify git cloner behaviour 2019-11-29 08:58:04 +00:00
Jonathan Wong
e46108ada0 Add in struct for mounted storage options 2019-11-28 15:43:17 -08:00
Alex Lundberg
9e16c8ca50 Add example for replicas in kustomization.yaml 2019-11-28 18:38:05 -05:00
Jeff Regan
763cb4e925 Merge pull request #1861 from monopole/anotherExampleMoved
Provide another high level example.
2019-11-28 08:47:43 -08:00
jregan
f0153997e1 Provide another high level example. 2019-11-28 08:18:12 -08:00
Jeff Regan
6d141f2ad0 Merge pull request #1860 from monopole/improveExampleVisibility
Start making examples more visible.
2019-11-28 08:17:07 -08:00
jregan
89e7b76d48 Start making examples more visible. 2019-11-28 07:23:37 -08:00
John
b7855dc959 Merge pull request #1 from utilitywarehouse/deep-git-clone-flag
add --deep_git_clone flag
2019-11-28 12:06:15 +00:00
john
6485a7cf3e add --deep_git_clone flag 2019-11-28 11:54:03 +00:00
Kubernetes Prow Robot
fc92f4acd0 Merge pull request #1856 from pwittrock/workspace
cmd/config: update naming of commands
2019-11-27 13:03:04 -08:00
Phillip Wittrock
52a5e6ec99 rename run-fns to run 2019-11-27 12:40:10 -08:00
Jeff Regan
752ddd087b Merge pull request #1845 from haiyanmeng/work
Make the crawler work
2019-11-27 12:07:23 -08:00
Jeff Regan
2b22bfc16b Merge pull request #1855 from monopole/makeWalkWork
Make filesys.Walk work.
2019-11-27 12:05:59 -08:00
Phillip Wittrock
7ce1f7e95a Update cmd/config docs from using yaml to using kustomize config 2019-11-27 11:59:45 -08:00
Jeffrey Regan
c722d4cd17 Make filesys walk work. 2019-11-27 11:33:10 -08:00
Kubernetes Prow Robot
1a9d62617e Merge pull request #1850 from pwittrock/workspace
cmd/config: Add examples and tutorials for config functions
2019-11-26 20:27:20 -08:00
Phillip Wittrock
dc66de6bf3 cmd/config: Add examples and tutorials for config functions
- Add examples under `functions`
- Add built-in tutorial for functions
2019-11-26 20:08:23 -08:00
Jeff Regan
cb64e19da3 Merge pull request #1849 from monopole/moarRefactor
More tests, better errors.
2019-11-26 19:46:24 -08:00
Haiyan Meng
9bba761a14 Add config for creating an ElasticSearch Cluster 2019-11-26 19:38:17 -08:00
jregan
f3e735153f More tests, better errors. 2019-11-26 19:29:06 -08:00
Haiyan Meng
31c5e89b1f Add String method to KustomizationDocument to avoid printing the
content of kustomization.yaml
2019-11-26 14:49:44 -08:00
Kubernetes Prow Robot
a2b84fce86 Merge pull request #1818 from mortent/WaitStatus
Add APIs for computing status based on fetching resource info from a cluster
2019-11-26 14:25:21 -08:00
Jonathan Wong
eccef3bb0d Add appropriate test for read only LocalVolume 2019-11-26 13:52:27 -08:00
Morten Torkildsen
a489f30183 Add APIs for computing status based on fetching resource info from a
cluster
2019-11-26 13:33:21 -08:00
Jonathan Wong
7eaaedf9f6 Make LocalVolume read only 2019-11-26 13:29:50 -08:00
Jeff Regan
d1b33e7468 Merge pull request #1847 from monopole/refactorForNewWalk
Refactor filesys to prep for new filesys.Walk
2019-11-26 12:31:24 -08:00
Jeffrey Regan
3b2988bda8 Refactor to prep for new filesys.Walk 2019-11-26 11:41:23 -08:00
Haiyan Meng
84b75afae4 Make the crawler work
1) add the crawler binary and fix the crawler library
2) remove the readiness probe in the search backend
3) add config for redis keystore
4) add github_api_secret.txt file with instructions
2019-11-26 09:50:51 -08:00
Kubernetes Prow Robot
73fb32c85a Merge pull request #1842 from pwittrock/workspace
cmd/config: add built-in tutorials
2019-11-26 07:51:11 -08:00
Phillip Wittrock
5876a8cce0 cmd/config: add built-in tutorials 2019-11-25 22:48:21 -08:00
Kubernetes Prow Robot
c9ee7f3787 Merge pull request #1840 from pwittrock/workspace
mdtogo: support for alternate license headers
2019-11-25 20:51:10 -08:00
Phillip Wittrock
23f9f819eb mdtogo: support for alternate license headers 2019-11-25 20:32:27 -08:00
Kubernetes Prow Robot
7fe518b0c6 Merge pull request #1837 from pwittrock/workspace
Publish `cmd/config` as Kustomize subcommand group
2019-11-25 13:26:09 -08:00
Phillip Wittrock
7baabf7a97 cmd/config: mark config command group as [Alpha] 2019-11-25 10:33:31 -08:00
Phillip Wittrock
4a65ea8056 Publish cmd/config as a Kustomize sub-command 2019-11-25 10:25:02 -08:00
Phillip Wittrock
598854440a cmd/config: expose target for embedding config commands 2019-11-25 10:20:34 -08:00
Jeff Regan
9f2163ae54 Merge pull request #1836 from monopole/unpinAllPlugins
Unpin all the plugins (non-builtins too).
2019-11-25 08:49:46 -08:00
Jeffrey Regan
ee8598dcbd Unpin all the plugins (non-builtins too). 2019-11-25 08:47:30 -08:00
Kubernetes Prow Robot
f8a25cc2b3 Merge pull request #1834 from bzub/fix_builtin_docs_fields_links
docs: Fix images and name{Prefix,Suffix} field links.
2019-11-25 08:17:26 -08:00
bzub
80dc481f9c Fix images + name{Prefix,Suffix} field links. 2019-11-23 14:29:06 -06:00
Jeff Regan
be4d6f77b2 Merge pull request #1832 from monopole/fixNits
Fix nit leftover from 1820
2019-11-22 16:21:58 -08:00
jregan
2a35bbffe4 Fix nit leftover from 1820 2019-11-22 16:02:59 -08:00
Jeff Regan
59a70525fa Merge pull request #1720 from oke-py/apps/v1
migrate Deployment from apps/v1beta2 to apps/v1
2019-11-22 15:55:35 -08:00
Jeff Regan
ee4f404ae8 Merge pull request #1820 from haiyanmeng/image
Skip updating empty containers in image tranformer
2019-11-22 15:53:28 -08:00
Haiyan Meng
752ca4b37c Skip updating empty containers in image tranformer 2019-11-22 14:18:59 -08:00
Haiyan Meng
964a5082b1 Add a unit test to demonstrate the issue 1747 2019-11-22 14:18:55 -08:00
Kubernetes Prow Robot
81d809f15d Merge pull request #1830 from pwittrock/docs-4
Add api documentation for annotations and fns
2019-11-22 14:18:42 -08:00
Jeff Regan
5f80480068 Merge pull request #1831 from monopole/unpinBuiltins
Unpin the builtin plugins.
2019-11-22 14:13:11 -08:00
Jeffrey Regan
416e1fcc1a Unpin the builtin plugins. 2019-11-22 14:08:24 -08:00
Phillip Wittrock
bf8af8efba kyaml: New documentation for annotations and fns (apis) 2019-11-22 13:10:39 -08:00
Kubernetes Prow Robot
980209e87c Merge pull request #1829 from pwittrock/docs-3
kyaml: refactor command documentation into .md files from go files
2019-11-22 13:02:42 -08:00
Phillip Wittrock
3345464b25 kyaml: refactor command documentation into .md files from go files
No new documentation added.
2019-11-22 12:22:25 -08:00
Phillip Wittrock
2a5f513bc3 Merge pull request #1828 from pwittrock/makefile
kyaml: fixup Makefile
2019-11-22 12:11:50 -08:00
Phillip Wittrock
f531ac065d kyaml: fixup Makefile
- Change name of generated binary to `config` to match module name
- Use GOBIN instead of GOPATH to simplify commands
- Export GOBIN environment variable to the `go generate` command so it can find built commands
2019-11-22 11:53:14 -08:00
Phillip Wittrock
b240092058 Merge pull request #1827 from pwittrock/makefile
Add utility for generating cobra documentation from .md files
2019-11-22 11:48:13 -08:00
Phillip Wittrock
f0ca8f9c1a Add utility for generating cobra documentation from .md files 2019-11-22 11:47:35 -08:00
Kubernetes Prow Robot
5d4e45c24d Merge pull request #1824 from ibidani/fix-docs-links
Fix docs broken files links as Github relative links
2019-11-22 08:07:28 -08:00
Idan Bidani
04516803f2 Fix docs broken links as Github relative links 2019-11-21 23:52:53 -05:00
Jeff Regan
56d57c3088 Merge pull request #1823 from kubernetes-sigs/revert-1631-replacement-poc
Revert "Replacement poc"
2019-11-21 18:32:46 -08:00
Jeff Regan
b6d760dc6f Update eschewedFeatures.md 2019-11-21 17:00:09 -08:00
Jonathan Wong
a7cff1c75b Add local volume support to container filters 2019-11-21 12:16:09 -08:00
Jonathan Wong
ff60138efd Merge branch 'master' of https://github.com/kubernetes-sigs/kustomize 2019-11-21 11:55:24 -08:00
Jonathan Wong
e6306f60f4 Add docs command boilerplate 2019-11-17 19:51:19 -08:00
Naoki Oketani
a8ece4b5f7 migrate Deploymnet from apps/v1beta2 to apps/v1 2019-11-12 15:02:54 +09:00
387 changed files with 13484 additions and 4168 deletions

View File

@@ -231,6 +231,7 @@ $(MYGOBIN)/helm:
.PHONY: clean
clean:
go clean --cache
rm -f $(builtinplugins)
rm -f $(MYGOBIN)/pluginator
rm -f $(MYGOBIN)/kustomize

View File

@@ -28,9 +28,9 @@ Since [v1.14][kubectl announcement] the kustomize build system has been included
| kubectl version | kustomize version |
|---------|--------|
| v1.16.0 | [v2.0.3](https://github.com/kubernetes-sigs/kustomize/tree/v2.0.3) |
| v1.15.x | [v2.0.3](https://github.com/kubernetes-sigs/kustomize/tree/v2.0.3) |
| v1.14.x | [v2.0.3](https://github.com/kubernetes-sigs/kustomize/tree/v2.0.3) |
| v1.16.0 | [v2.0.3](/../../tree/v2.0.3) |
| v1.15.x | [v2.0.3](/../../tree/v2.0.3) |
| v1.14.x | [v2.0.3](/../../tree/v2.0.3) |
For examples and guides for using the kubectl integration please see the [kubectl book] or the [kubernetes documentation].
@@ -167,7 +167,7 @@ is governed by the [Kubernetes Code of Conduct].
[eschewed feature list]: docs/eschewedFeatures.md
[imageBase]: docs/images/base.jpg
[imageOverlay]: docs/images/overlay.jpg
[kind/feature]: https://github.com/kubernetes-sigs/kustomize/labels/kind%2Ffeature
[kind/feature]: /../../labels/kind%2Ffeature
[kubectl announcement]: https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement
[kubectl book]: https://kubectl.docs.kubernetes.io/pages/app_customization/introduction.html
[kubernetes documentation]: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
@@ -175,12 +175,12 @@ is governed by the [Kubernetes Code of Conduct].
[kustomization]: docs/glossary.md#kustomization
[overlay]: docs/glossary.md#overlay
[overlays]: docs/glossary.md#overlay
[release page]: https://github.com/kubernetes-sigs/kustomize/releases
[release page]: /../../releases
[resource]: docs/glossary.md#resource
[resources]: docs/glossary.md#resource
[sig-cli]: https://github.com/kubernetes/community/blob/master/sig-cli/README.md
[variant]: docs/glossary.md#variant
[variants]: docs/glossary.md#variant
[v2.0.3]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v2.0.3
[v2.1.0]: https://github.com/kubernetes-sigs/kustomize/releases/tag/v2.1.0
[v2.0.3]: /../../releases/tag/v2.0.3
[v2.1.0]: /../../releases/tag/v2.1.0
[workflows]: docs/workflows.md

View File

@@ -17,7 +17,7 @@ type AnnotationsTransformerPlugin struct {
}
func (p *AnnotationsTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Annotations = nil
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)

View File

@@ -15,7 +15,7 @@ type HashTransformerPlugin struct {
}
func (p *HashTransformerPlugin) Config(
h *resmap.PluginHelpers, config []byte) (err error) {
h *resmap.PluginHelpers, _ []byte) (err error) {
p.hasher = h.ResmapFactory().RF().Hasher()
return nil
}

View File

@@ -23,7 +23,7 @@ type ImageTagTransformerPlugin struct {
}
func (p *ImageTagTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
_ *resmap.PluginHelpers, c []byte) (err error) {
p.ImageTag = types.Image{}
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
@@ -82,7 +82,7 @@ func (p *ImageTagTransformerPlugin) findAndReplaceImage(obj map[string]interface
updated := false
for _, path := range paths {
containers, found := obj[path]
if found {
if found && containers != nil {
if _, err := p.updateContainers(containers); err != nil {
return err
}

View File

@@ -17,7 +17,7 @@ type LabelTransformerPlugin struct {
}
func (p *LabelTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Labels = nil
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)

View File

@@ -20,7 +20,7 @@ type LegacyOrderTransformerPlugin struct{}
// Nothing needed for configuration.
func (p *LegacyOrderTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
_ *resmap.PluginHelpers, _ []byte) (err error) {
return nil
}

View File

@@ -22,7 +22,7 @@ type NamespaceTransformerPlugin struct {
}
func (p *NamespaceTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Namespace = ""
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
@@ -75,7 +75,7 @@ func (p *NamespaceTransformerPlugin) applicableFieldSpecs(id resid.ResId) []type
}
func (p *NamespaceTransformerPlugin) changeNamespace(
referrer *resource.Resource) func(in interface{}) (interface{}, error) {
_ *resource.Resource) func(in interface{}) (interface{}, error) {
return func(in interface{}) (interface{}, error) {
switch in.(type) {
case string:

View File

@@ -33,7 +33,7 @@ var prefixSuffixFieldSpecsToSkip = []types.FieldSpec{
}
func (p *PrefixSuffixTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Prefix = ""
p.Suffix = ""
p.FieldSpecs = nil

View File

@@ -22,8 +22,7 @@ type ReplicaCountTransformerPlugin struct {
}
func (p *ReplicaCountTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Replica = types.Replica{}
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)

View File

@@ -6,34 +6,8 @@ package filesys
import (
"io"
"os"
"time"
)
var _ os.FileInfo = &fileInfo{}
// fileInfo implements os.FileInfo for a fileInMemory instance.
type fileInfo struct {
*fileInMemory
}
// Name returns the name of the file
func (fi *fileInfo) Name() string { return fi.name }
// Size returns the size of the file
func (fi *fileInfo) Size() int64 { return int64(len(fi.content)) }
// Mode returns the file mode
func (fi *fileInfo) Mode() os.FileMode { return 0777 }
// ModTime returns the modification time
func (fi *fileInfo) ModTime() time.Time { return time.Time{} }
// IsDir returns if it is a directory
func (fi *fileInfo) IsDir() bool { return fi.dir }
// Sys should return underlying data source, but it now returns nil
func (fi *fileInfo) Sys() interface{} { return nil }
// File groups the basic os.File methods.
type File interface {
io.ReadWriteCloser

34
api/filesys/fileinfo.go Normal file
View File

@@ -0,0 +1,34 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filesys
import (
"os"
"time"
)
var _ os.FileInfo = fileInfo{}
// fileInfo implements os.FileInfo for a fileInMemory instance.
type fileInfo struct {
node *fsNode
}
// Name returns the name of the file
func (fi fileInfo) Name() string { return fi.node.Name() }
// Size returns the size of the file
func (fi fileInfo) Size() int64 { return fi.node.Size() }
// Mode returns the file mode
func (fi fileInfo) Mode() os.FileMode { return 0777 }
// ModTime returns a bogus time
func (fi fileInfo) ModTime() time.Time { return time.Time{} }
// IsDir returns true if it is a directory
func (fi fileInfo) IsDir() bool { return fi.node.isNodeADir() }
// Sys should return underlying data source, but it now returns nil
func (fi fileInfo) Sys() interface{} { return nil }

View File

@@ -1,56 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filesys
import (
"bytes"
"os"
)
var _ File = &fileInMemory{}
// fileInMemory implements File in-memory for tests.
type fileInMemory struct {
name string
content []byte
dir bool
open bool
}
// makeDir makes a fake directory.
func makeDir(name string) *fileInMemory {
return &fileInMemory{name: name, dir: true}
}
// Close marks the fake file closed.
func (f *fileInMemory) Close() error {
f.open = false
return nil
}
// Read never fails, and doesn't mutate p.
func (f *fileInMemory) Read(p []byte) (n int, err error) {
return len(p), nil
}
// Write saves the contents of the argument to memory.
func (f *fileInMemory) Write(p []byte) (n int, err error) {
f.content = p
return len(p), nil
}
// ContentMatches returns true if v matches fake file's content.
func (f *fileInMemory) ContentMatches(v []byte) bool {
return bytes.Equal(v, f.content)
}
// GetContent the content of a fake file.
func (f *fileInMemory) GetContent() []byte {
return f.content
}
// Stat returns nil.
func (f *fileInMemory) Stat() (os.FileInfo, error) {
return nil, nil
}

View File

@@ -8,13 +8,20 @@ import (
"path/filepath"
)
const (
Separator = string(filepath.Separator)
SelfDir = "."
ParentDir = ".."
)
// FileSystem groups basic os filesystem methods.
// It's supposed be functional subset of https://golang.org/pkg/os
type FileSystem interface {
// Create a file.
Create(name string) (File, error)
Create(path string) (File, error)
// MkDir makes a directory.
Mkdir(path string) error
// MkDir makes a directory path, creating intervening directories.
// MkDirAll makes a directory path, creating intervening directories.
MkdirAll(path string) error
// RemoveAll removes path and any children it contains.
RemoveAll(path string) error
@@ -30,11 +37,13 @@ type FileSystem interface {
CleanedAbs(path string) (ConfirmedDir, string, error)
// Exists is true if the path exists in the file system.
Exists(path string) bool
// Glob returns the list of matching files
// Glob returns the list of matching files,
// emulating https://golang.org/pkg/path/filepath/#Glob
Glob(pattern string) ([]string, error)
// ReadFile returns the contents of the file at the given path.
ReadFile(path string) ([]byte, error)
// WriteFile writes the data to a file at the given path.
// WriteFile writes the data to a file at the given path,
// overwriting anything that's already there.
WriteFile(path string, data []byte) error
// Walk walks the file system with the given WalkFunc.
Walk(path string, walkFn filepath.WalkFunc) error

View File

@@ -1,223 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filesys
import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
)
var _ FileSystem = &fsInMemory{}
// fsInMemory implements FileSystem using a in-memory filesystem
// primarily for use in tests.
type fsInMemory struct {
m map[string]*fileInMemory
}
// MakeFsInMemory returns an instance of fsInMemory with no files in it.
func MakeFsInMemory() FileSystem {
result := &fsInMemory{m: map[string]*fileInMemory{}}
result.Mkdir(separator)
return result
}
const (
separator = string(filepath.Separator)
doubleSep = separator + separator
)
// Create assures a fake file appears in the in-memory file system.
func (fs *fsInMemory) Create(name string) (File, error) {
f := &fileInMemory{}
f.open = true
fs.m[name] = f
return fs.m[name], nil
}
// Mkdir assures a fake directory appears in the in-memory file system.
func (fs *fsInMemory) Mkdir(name string) error {
fs.m[name] = makeDir(name)
return nil
}
// MkdirAll delegates to Mkdir
func (fs *fsInMemory) MkdirAll(name string) error {
return fs.Mkdir(name)
}
// RemoveAll presumably does rm -r on a path.
// There's no error.
func (fs *fsInMemory) RemoveAll(name string) error {
var toRemove []string
for k := range fs.m {
if strings.HasPrefix(k, name) {
toRemove = append(toRemove, k)
}
}
for _, k := range toRemove {
delete(fs.m, k)
}
return nil
}
// Open returns a fake file in the open state.
func (fs *fsInMemory) Open(name string) (File, error) {
if _, found := fs.m[name]; !found {
return nil, fmt.Errorf("file %q cannot be opened", name)
}
return fs.m[name], nil
}
// CleanedAbs cannot fail.
func (fs *fsInMemory) CleanedAbs(path string) (ConfirmedDir, string, error) {
if fs.IsDir(path) {
return ConfirmedDir(path), "", nil
}
d := filepath.Dir(path)
if d == path {
return ConfirmedDir(d), "", nil
}
return ConfirmedDir(d), filepath.Base(path), nil
}
// Exists returns true if file is known.
func (fs *fsInMemory) Exists(name string) bool {
_, found := fs.m[name]
return found
}
// Glob returns the list of matching files
func (fs *fsInMemory) Glob(pattern string) ([]string, error) {
var result []string
for p := range fs.m {
if fs.pathMatch(p, pattern) {
result = append(result, p)
}
}
sort.Strings(result)
return result, nil
}
// IsDir returns true if the file exists and is a directory.
func (fs *fsInMemory) IsDir(name string) bool {
f, found := fs.m[name]
if found && f.dir {
return true
}
if !strings.HasSuffix(name, separator) {
name = name + separator
}
for k := range fs.m {
if strings.HasPrefix(k, name) {
return true
}
}
return false
}
// ReadFile always returns an empty bytes and error depending on content of m.
func (fs *fsInMemory) ReadFile(name string) ([]byte, error) {
if ff, found := fs.m[name]; found {
return ff.content, nil
}
return nil, fmt.Errorf("cannot read file %q", name)
}
// WriteFile always succeeds and does nothing.
func (fs *fsInMemory) WriteFile(name string, c []byte) error {
ff := &fileInMemory{}
ff.Write(c)
fs.m[name] = ff
return nil
}
// Walk implements filepath.Walk using the fake filesystem.
func (fs *fsInMemory) Walk(path string, walkFn filepath.WalkFunc) error {
info, err := fs.lstat(path)
if err != nil {
err = walkFn(path, info, err)
} else {
err = fs.walk(path, info, walkFn)
}
if err == filepath.SkipDir {
return nil
}
return err
}
func (fs *fsInMemory) pathMatch(path, pattern string) bool {
match, _ := filepath.Match(pattern, path)
return match
}
func (fs *fsInMemory) lstat(path string) (*fileInfo, error) {
f, found := fs.m[path]
if !found {
return nil, os.ErrNotExist
}
return &fileInfo{f}, nil
}
func (fs *fsInMemory) join(elem ...string) string {
for i, e := range elem {
if e != "" {
return strings.Replace(
strings.Join(elem[i:], separator), doubleSep, separator, -1)
}
}
return ""
}
func (fs *fsInMemory) readDirNames(path string) []string {
var names []string
if !strings.HasSuffix(path, separator) {
path += separator
}
pathSegments := strings.Count(path, separator)
for name := range fs.m {
if name == path {
continue
}
if strings.Count(name, separator) > pathSegments {
continue
}
if strings.HasPrefix(name, path) {
names = append(names, filepath.Base(name))
}
}
sort.Strings(names)
return names
}
func (fs *fsInMemory) walk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
if !info.IsDir() {
return walkFn(path, info, nil)
}
names := fs.readDirNames(path)
if err := walkFn(path, info, nil); err != nil {
return err
}
for _, name := range names {
filename := fs.join(path, name)
fileInfo, err := fs.lstat(filename)
if err != nil {
if err := walkFn(filename, fileInfo, os.ErrNotExist); err != nil && err != filepath.SkipDir {
return err
}
} else {
err = fs.walk(filename, fileInfo, walkFn)
if err != nil {
if !fileInfo.IsDir() || err != filepath.SkipDir {
return err
}
}
}
}
return nil
}

View File

@@ -1,149 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filesys_test
import (
"bytes"
"reflect"
"testing"
. "sigs.k8s.io/kustomize/api/filesys"
)
func TestExists(t *testing.T) {
fSys := MakeFsInMemory()
if fSys.Exists("foo") {
t.Fatalf("expected no foo")
}
fSys.Mkdir("/")
if !fSys.IsDir("/") {
t.Fatalf("expected dir at /")
}
}
func TestIsDir(t *testing.T) {
fSys := MakeFsInMemory()
expectedName := "my-dir"
err := fSys.Mkdir(expectedName)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
shouldExist(t, fSys, expectedName)
if !fSys.IsDir(expectedName) {
t.Fatalf(expectedName + " should be a dir")
}
}
func shouldExist(t *testing.T, fSys FileSystem, name string) {
if !fSys.Exists(name) {
t.Fatalf(name + " should exist")
}
}
func shouldNotExist(t *testing.T, fSys FileSystem, name string) {
if fSys.Exists(name) {
t.Fatalf(name + " should not exist")
}
}
func TestRemoveAll(t *testing.T) {
fSys := MakeFsInMemory()
fSys.WriteFile("/foo/project/file.yaml", []byte("Unused"))
fSys.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused"))
fSys.WriteFile("/foo/apple/subdir/file.yaml", []byte("Unused"))
shouldExist(t, fSys, "/foo/project/file.yaml")
shouldExist(t, fSys, "/foo/project/subdir/file.yaml")
shouldExist(t, fSys, "/foo/apple/subdir/file.yaml")
err := fSys.RemoveAll("/foo/project")
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
shouldNotExist(t, fSys, "/foo/project/file.yaml")
shouldNotExist(t, fSys, "/foo/project/subdir/file.yaml")
shouldExist(t, fSys, "/foo/apple/subdir/file.yaml")
}
func TestIsDirDeeper(t *testing.T) {
fSys := MakeFsInMemory()
fSys.WriteFile("/foo/project/file.yaml", []byte("Unused"))
fSys.WriteFile("/foo/project/subdir/file.yaml", []byte("Unused"))
if !fSys.IsDir("/") {
t.Fatalf("/ should be a dir")
}
if !fSys.IsDir("/foo") {
t.Fatalf("/foo should be a dir")
}
if !fSys.IsDir("/foo/project") {
t.Fatalf("/foo/project should be a dir")
}
if fSys.IsDir("/fo") {
t.Fatalf("/fo should not be a dir")
}
if fSys.IsDir("/x") {
t.Fatalf("/x should not be a dir")
}
}
func TestCreate(t *testing.T) {
fSys := MakeFsInMemory()
f, err := fSys.Create("foo")
if f == nil {
t.Fatalf("expected file")
}
if err != nil {
t.Fatalf("unexpected error")
}
shouldExist(t, fSys, "foo")
}
func TestReadFile(t *testing.T) {
fSys := MakeFsInMemory()
f, err := fSys.Create("foo")
if f == nil {
t.Fatalf("expected file")
}
if err != nil {
t.Fatalf("unexpected error")
}
content, err := fSys.ReadFile("foo")
if len(content) != 0 {
t.Fatalf("expected no content")
}
if err != nil {
t.Fatalf("expected no error")
}
}
func TestWriteFile(t *testing.T) {
fSys := MakeFsInMemory()
c := []byte("heybuddy")
err := fSys.WriteFile("foo", c)
if err != nil {
t.Fatalf("expected no error")
}
content, err := fSys.ReadFile("foo")
if err != nil {
t.Fatalf("expected read to work: %v", err)
}
if !bytes.Equal(c, content) {
t.Fatalf("incorrect content: %v", content)
}
}
func TestGlob(t *testing.T) {
fSys := MakeFsInMemory()
fSys.Create("dir/foo")
fSys.Create("dir/bar")
files, err := fSys.Glob("dir/*")
if err != nil {
t.Fatalf("expected no error")
}
expected := []string{
"dir/bar",
"dir/foo",
}
if !reflect.DeepEqual(files, expected) {
t.Fatalf("incorrect files found by glob: %v", files)
}
}

557
api/filesys/fsnode.go Normal file
View File

@@ -0,0 +1,557 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filesys
import (
"bytes"
"fmt"
"log"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"github.com/pkg/errors"
)
var _ File = &fsNode{}
var _ FileSystem = &fsNode{}
// fsNode is either a file or a directory.
type fsNode struct {
// What node owns me?
parent *fsNode
// Value to return as the Name() when the
// parent is nil.
nilParentName string
// A directory mapping names to nodes.
// If dir is nil, then self node is a file.
// If dir is non-nil, then self node is a directory,
// albeit possibly an empty directory.
dir map[string]*fsNode
// if this node is a file, this is the content.
content []byte
// if this node is a file, this tracks whether or
// not it is "open".
open bool
}
// MakeEmptyDirInMemory returns an empty directory.
// The paths of nodes in this object will never
// report a leading Separator, meaning they
// aren't "absolute" in the sense defined by
// https://golang.org/pkg/path/filepath/#IsAbs.
func MakeEmptyDirInMemory() *fsNode {
return &fsNode{
dir: make(map[string]*fsNode),
}
}
// MakeFsInMemory returns an empty 'file system'.
// The paths of nodes in this object will always
// report a leading Separator, meaning they
// are "absolute" in the sense defined by
// https://golang.org/pkg/path/filepath/#IsAbs.
// This is a relevant difference when using Walk,
// Glob, Match, etc.
func MakeFsInMemory() FileSystem {
return &fsNode{
nilParentName: Separator,
dir: make(map[string]*fsNode),
}
}
// Name returns the name of the node.
func (n *fsNode) Name() string {
if n.parent == nil {
// Unable to lookup name in parent.
return n.nilParentName
}
if !n.parent.isNodeADir() {
log.Fatal("parent not a dir")
}
for key, value := range n.parent.dir {
if value == n {
return key
}
}
log.Fatal("unable to find fsNode name")
return ""
}
// Path returns the full path to the node.
func (n *fsNode) Path() string {
if n.parent == nil {
return n.nilParentName
}
if !n.parent.isNodeADir() {
log.Fatal("parent not a dir, structural error")
}
return filepath.Join(n.parent.Path(), n.Name())
}
// mySplit trims trailing separators from the directory
// result of filepath.Split.
func mySplit(s string) (string, string) {
dName, fName := filepath.Split(s)
return StripTrailingSeps(dName), fName
}
func (n *fsNode) addFile(name string, c []byte) (result *fsNode, err error) {
parent := n
dName, fileName := mySplit(name)
if dName != "" {
parent, err = parent.addDir(dName)
if err != nil {
return nil, err
}
}
if !isLegalFileNameForCreation(fileName) {
return nil, fmt.Errorf(
"illegal name '%s' in file creation", fileName)
}
result, ok := parent.dir[fileName]
if ok {
// File already exists; overwrite it.
result.content = c
return result, nil
}
result = &fsNode{
content: c,
parent: parent,
}
parent.dir[fileName] = result
return result, nil
}
// Create implements FileSystem.
// Create makes an empty file.
func (n *fsNode) Create(path string) (result File, err error) {
return n.AddFile(path, []byte{})
}
// WriteFile implements FileSystem.
func (n *fsNode) WriteFile(path string, d []byte) error {
_, err := n.AddFile(path, d)
return err
}
// AddFile adds a file and any necessary containing
// directories to the node.
func (n *fsNode) AddFile(
name string, c []byte) (result *fsNode, err error) {
if n.dir == nil {
return nil, fmt.Errorf(
"cannot add a file to a non-directory '%s'", n.Name())
}
return n.addFile(cleanQueryPath(name), c)
}
func (n *fsNode) addDir(path string) (result *fsNode, err error) {
parent := n
dName, subDirName := mySplit(path)
if dName != "" {
parent, err = n.addDir(dName)
if err != nil {
return nil, err
}
}
switch subDirName {
case "", SelfDir:
return n, nil
case ParentDir:
if n.parent == nil {
return nil, fmt.Errorf(
"cannot add a directory above '%s'", n.Path())
}
return n.parent, nil
default:
if !isLegalFileNameForCreation(subDirName) {
return nil, fmt.Errorf(
"illegal name '%s' in directory creation", subDirName)
}
result, ok := parent.dir[subDirName]
if ok {
if result.isNodeADir() {
// it's already there.
return result, nil
}
return nil, fmt.Errorf(
"cannot make dir '%s'; a file of that name already exists in '%s'",
subDirName, parent.Name())
}
result = &fsNode{
dir: make(map[string]*fsNode),
parent: parent,
}
parent.dir[subDirName] = result
return result, nil
}
}
// Mkdir implements FileSystem.
// Mkdir creates a directory.
func (n *fsNode) Mkdir(path string) error {
_, err := n.AddDir(path)
return err
}
// MkdirAll implements FileSystem.
// MkdirAll creates a directory.
func (n *fsNode) MkdirAll(path string) error {
_, err := n.AddDir(path)
return err
}
// AddDir adds a directory to the node, not complaining
// if it is already there.
func (n *fsNode) AddDir(path string) (result *fsNode, err error) {
if n.dir == nil {
return nil, fmt.Errorf(
"cannot add a directory to file node '%s'", n.Name())
}
return n.addDir(cleanQueryPath(path))
}
// CleanedAbs implements FileSystem.
func (n *fsNode) CleanedAbs(path string) (ConfirmedDir, string, error) {
node, err := n.Find(path)
if err != nil {
return "", "", errors.Wrap(err, "unable to clean")
}
if node == nil {
return "", "", fmt.Errorf("'%s' doesn't exist", path)
}
if node.isNodeADir() {
return ConfirmedDir(node.Path()), "", nil
}
return ConfirmedDir(node.parent.Path()), node.Name(), nil
}
// Exists implements FileSystem.
// Exists returns true if the path exists.
func (n *fsNode) Exists(path string) bool {
if !n.isNodeADir() {
return n.Name() == path
}
result, err := n.Find(path)
if err != nil {
return false
}
return result != nil
}
func cleanQueryPath(path string) string {
// Always ignore leading separator?
// Remember that filepath.Clean returns "." if
// given an empty string argument.
return filepath.Clean(StripLeadingSeps(path))
}
// Find finds the given node, else nil if not found.
// Return error on structural/argument errors.
func (n *fsNode) Find(path string) (*fsNode, error) {
if !n.isNodeADir() {
return nil, fmt.Errorf("can only find inside a dir")
}
if path == "" {
// Special case; check *before* cleaning and *before*
// comparison to nilParentName.
return nil, nil
}
if (n.parent == nil && path == n.nilParentName) || path == SelfDir {
// Special case
return n, nil
}
return n.findIt(cleanQueryPath(path))
}
func (n *fsNode) findIt(path string) (result *fsNode, err error) {
parent := n
dName, item := mySplit(path)
if dName != "" {
parent, err = n.findIt(dName)
if err != nil {
return nil, err
}
if parent == nil {
// all done, target doesn't exist.
return nil, nil
}
}
if !parent.isNodeADir() {
return nil, fmt.Errorf("'%s' is not a directory", parent.Path())
}
return parent.dir[item], nil
}
// RemoveAll implements FileSystem.
// RemoveAll removes an item and everything it contains.
func (n *fsNode) RemoveAll(path string) error {
result, err := n.Find(path)
if err != nil {
return err
}
if result == nil {
return fmt.Errorf("cannot find '%s' to remove it", path)
}
return result.Remove()
}
// Remove drop the node, and everything it contains, from its parent.
func (n *fsNode) Remove() error {
if n.parent == nil {
return fmt.Errorf("cannot remove a root node")
}
if !n.parent.isNodeADir() {
log.Fatal("parent not a dir")
}
for key, value := range n.parent.dir {
if value == n {
delete(n.parent.dir, key)
return nil
}
}
log.Fatal("unable to find self in parent")
return nil
}
// isNodeADir returns true if the node is a directory.
// Cannot collide with the poorly named "IsDir".
func (n *fsNode) isNodeADir() bool {
return n.dir != nil
}
// IsDir implements FileSystem.
// IsDir returns true if the argument resolves
// to a directory rooted at the node.
func (n *fsNode) IsDir(path string) bool {
result, err := n.Find(path)
if err != nil || result == nil {
return false
}
return result.isNodeADir()
}
// Size returns the size of the node.
func (n *fsNode) Size() int64 {
if n.isNodeADir() {
return int64(len(n.dir))
}
return int64(len(n.content))
}
// Open implements FileSystem.
// Open opens the node for reading (just marks it).
func (n *fsNode) Open(path string) (File, error) {
result, err := n.Find(path)
if err != nil {
return nil, err
}
if result == nil {
return nil, fmt.Errorf("cannot find '%s' to open it", path)
}
result.open = true
return result, nil
}
// Close marks the node closed.
func (n *fsNode) Close() error {
n.open = false
return nil
}
// ReadFile implements FileSystem.
func (n *fsNode) ReadFile(path string) (c []byte, err error) {
result, err := n.Find(path)
if err != nil {
return nil, err
}
if result == nil {
return nil, fmt.Errorf("cannot find '%s' to read it", path)
}
c = make([]byte, len(result.content))
_, err = result.Read(c)
return c, err
}
// Read returns the content of the file node.
func (n *fsNode) Read(d []byte) (c int, err error) {
if n.isNodeADir() {
return 0, fmt.Errorf(
"cannot read content from non-file '%s'", n.Path())
}
return copy(d, n.content), nil
}
// Write saves the contents of the argument to the file node.
func (n *fsNode) Write(p []byte) (c int, err error) {
if n.isNodeADir() {
return 0, fmt.Errorf(
"cannot write content to non-file '%s'", n.Path())
}
n.content = make([]byte, len(p))
return copy(n.content, p), nil
}
// ContentMatches returns true if v matches fake file's content.
func (n *fsNode) ContentMatches(v []byte) bool {
return bytes.Equal(v, n.content)
}
// GetContent the content of a fake file.
func (n *fsNode) GetContent() []byte {
return n.content
}
// Stat returns an instance of FileInfo.
func (n *fsNode) Stat() (os.FileInfo, error) {
return fileInfo{node: n}, nil
}
// Walk implements FileSystem.
func (n *fsNode) Walk(path string, walkFn filepath.WalkFunc) error {
result, err := n.Find(path)
if err != nil {
return err
}
if result == nil {
return fmt.Errorf("cannot find '%s' to walk it", path)
}
return result.WalkMe(walkFn)
}
// Walk runs the given walkFn on each node.
func (n *fsNode) WalkMe(walkFn filepath.WalkFunc) error {
fi, err := n.Stat()
// always visit self first
err = walkFn(n.Path(), fi, err)
if !n.isNodeADir() {
// it's a file, so nothing more to do
return err
}
// process self as a directory
if err == filepath.SkipDir {
return nil
}
// Walk is supposed to visit in lexical order.
for _, k := range n.sortedDirEntries() {
if err := n.dir[k].WalkMe(walkFn); err != nil {
if err == filepath.SkipDir {
// stop processing this directory
break
}
// bail out completely
return err
}
}
return nil
}
func (n *fsNode) sortedDirEntries() []string {
keys := make([]string, len(n.dir))
i := 0
for k := range n.dir {
keys[i] = k
i++
}
sort.Strings(keys)
return keys
}
// FileCount returns a count of files.
// Directories, empty or otherwise, not counted.
func (n *fsNode) FileCount() int {
count := 0
n.WalkMe(func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
count++
}
return nil
})
return count
}
func (n *fsNode) DebugPrint() {
n.WalkMe(func(path string, info os.FileInfo, err error) error {
if err != nil {
fmt.Printf("err '%v' at path %q\n", err, path)
return nil
}
if info.IsDir() {
if info.Size() == 0 {
fmt.Println("empty dir: " + path)
}
} else {
fmt.Println(" file: " + path)
}
return nil
})
}
var legalFileNamePattern = regexp.MustCompile("^[a-zA-Z0-9-_.]+$")
// This rules enforced here should be simpler and tighter
// than what's allowed on a real OS.
// Should be fine for testing or in-memory purposes.
func isLegalFileNameForCreation(n string) bool {
if n == "" || n == SelfDir || !legalFileNamePattern.MatchString(n) {
return false
}
return !strings.Contains(n, ParentDir)
}
// RegExpGlob returns a list of file paths matching the regexp.
// Excludes directories.
func (n *fsNode) RegExpGlob(pattern string) ([]string, error) {
var result []string
var expression = regexp.MustCompile(pattern)
n.WalkMe(func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
if expression.MatchString(path) {
result = append(result, path)
}
}
return nil
})
sort.Strings(result)
return result, nil
}
// Glob implements FileSystem.
// Glob returns the list of file paths matching
// per filepath.Match semantics, i.e. unlike RegExpGlob,
// Match("foo/a*") will not match sub-sub directories of foo.
// This is how /bin/ls behaves.
func (n *fsNode) Glob(pattern string) ([]string, error) {
var result []string
n.WalkMe(func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
match, err := filepath.Match(pattern, path)
if err != nil {
return err
}
if match {
result = append(result, path)
}
}
return nil
})
sort.Strings(result)
return result, nil
}

788
api/filesys/fsnode_test.go Normal file
View File

@@ -0,0 +1,788 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filesys
import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"testing"
)
const content = `
Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
`
const shortContent = "hi"
var topCases = []pathCase{
{
what: "dotdot",
arg: ParentDir,
errStr: "illegal name '..' in file creation",
},
{
what: "empty",
arg: "",
name: "",
errStr: "illegal name '.' in file creation",
},
{
what: "simple",
arg: "bob",
name: "bob",
path: "bob",
},
{
what: "longer",
arg: filepath.Join("longer", "bob"),
name: "bob",
path: filepath.Join("longer", "bob"),
},
{
what: "longer yet",
arg: filepath.Join("longer", "foo", "bar", "beans", "bob"),
name: "bob",
path: filepath.Join("longer", "foo", "bar", "beans", "bob"),
},
{
what: "tricky",
arg: filepath.Join("bob", ParentDir, "sally"),
name: "sally",
path: "sally",
},
{
what: "trickier",
arg: filepath.Join("bob", "sally", ParentDir, ParentDir, "jean"),
name: "jean",
path: "jean",
},
}
func TestMakeEmptyDirInMemory(t *testing.T) {
n := MakeEmptyDirInMemory()
if !n.isNodeADir() {
t.Fatalf("not a directory")
}
if n.Size() != 0 {
t.Fatalf("unexpected size %d", n.Size())
}
if n.Name() != "" {
t.Fatalf("unexpected name '%s'", n.Name())
}
if n.Path() != "" {
t.Fatalf("unexpected path '%s'", n.Path())
}
runBasicOperations(
t, "MakeEmptyDirInMemory", false, topCases, n)
}
func TestMakeFsInMemory(t *testing.T) {
runBasicOperations(
t, "MakeFsInMemory", true, topCases, MakeFsInMemory())
}
//nolint:gocyclo
func runBasicOperations(
t *testing.T, tName string, isFSysRooted bool,
cases []pathCase, fSys FileSystem) {
buff := make([]byte, 500)
for _, c := range cases {
err := fSys.WriteFile(c.arg, []byte(content))
if c.errStr != "" {
if err == nil {
t.Fatalf("%s; expected error writing to '%s'!", c.what, c.arg)
}
if !strings.Contains(err.Error(), c.errStr) {
t.Fatalf("%s; expected err containing '%s', got '%v'",
c.what, c.errStr, err)
}
continue
}
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
if !fSys.Exists(c.path) {
t.Fatalf("%s; expect existence of '%s'", c.what, c.path)
}
stuff, err := fSys.ReadFile(c.path)
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
if string(stuff) != content {
t.Fatalf("%s; unexpected content '%s'", c.what, stuff)
}
f, err := fSys.Open(c.arg)
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
fi, err := f.Stat()
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
if fi.Name() != c.name {
t.Fatalf("%s; expected name '%s', got '%s'", c.what, c.name, fi.Name())
}
count, err := f.Read(buff)
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
if string(buff[:count]) != content {
t.Fatalf("%s; unexpected buff '%s'", c.what, buff)
}
count, err = f.Write([]byte(shortContent))
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
if count != len(shortContent) {
t.Fatalf("%s; unexpected count: %d", c.what, len(shortContent))
}
stuff, err = fSys.ReadFile(c.path)
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
if string(stuff) != shortContent {
t.Fatalf("%s; unexpected content '%s'", c.what, stuff)
}
}
var actualPaths []string
var err error
prefix := ""
{
root := SelfDir
if isFSysRooted {
root = Separator
prefix = Separator
}
err = fSys.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
fmt.Printf("err '%v' at path %q\n", err, path)
return nil
}
if !info.IsDir() {
actualPaths = append(actualPaths, path)
}
return nil
})
}
if err != nil {
t.Fatalf("unexpected error %v", err)
}
var expectedPaths []string
for _, c := range cases {
if c.errStr == "" {
expectedPaths = append(expectedPaths, prefix+c.path)
}
}
sort.Strings(expectedPaths)
assertEqualStringSlices(t, expectedPaths, actualPaths, tName)
}
type pathCase struct {
what string
arg string
name string
path string
errStr string
}
func TestAddDir(t *testing.T) {
cases := []pathCase{
{
what: "dotdot",
arg: ParentDir,
errStr: "cannot add a directory above ''",
},
{
what: "empty",
arg: "",
name: "",
path: "",
},
{
what: "simple",
arg: "bob",
name: "bob",
path: "bob",
},
{
what: "longer",
arg: filepath.Join("longer", "bob"),
name: "bob",
path: filepath.Join("longer", "bob"),
},
{
what: "longer yet",
arg: filepath.Join("longer", "foo", "bar", "beans", "bob"),
name: "bob",
path: filepath.Join("longer", "foo", "bar", "beans", "bob"),
},
{
what: "tricky",
arg: filepath.Join("bob", ParentDir, "sally"),
name: "sally",
path: "sally",
},
{
what: "trickier",
arg: filepath.Join("bob", "sally", ParentDir, ParentDir, "jean"),
name: "jean",
path: "jean",
},
}
for _, c := range cases {
n := MakeEmptyDirInMemory()
f, err := n.AddDir(c.arg)
if c.errStr != "" {
if err == nil {
t.Fatalf("%s; expected error!", c.what)
}
if !strings.Contains(err.Error(), c.errStr) {
t.Fatalf(
"%s; expected error with '%s', got '%v'",
c.what, c.errStr, err)
}
continue
}
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
checkNode(t, c.what, f, c.name, 0, true, c.path)
checkOsStat(t, c.what, f, f.Name(), 0, true)
}
}
var bagOfCases = []pathCase{
{
what: "empty",
arg: "",
errStr: "illegal name '.' in file creation",
},
{
what: "simple",
arg: "bob",
name: "bob",
path: "bob",
},
{
what: "longer",
arg: filepath.Join("longer", "bob"),
name: "bob",
path: filepath.Join("longer", "bob"),
},
{
what: "longer",
arg: filepath.Join("longer", "sally"),
name: "sally",
path: filepath.Join("longer", "sally"),
},
{
what: "even longer",
arg: filepath.Join("longer", "than", "the", "other", "bob"),
name: "bob",
path: filepath.Join("longer", "than", "the", "other", "bob"),
},
{
what: "even longer",
arg: filepath.Join("even", "much", "longer", "than", "the", "other", "bob"),
name: "bob",
path: filepath.Join("even", "much", "longer", "than", "the", "other", "bob"),
},
}
func TestAddFile(t *testing.T) {
n := MakeEmptyDirInMemory()
if n.FileCount() != 0 {
t.Fatalf("expected no files, got %d", n.FileCount())
}
expectedFileCount := 0
for _, c := range bagOfCases {
f, err := n.AddFile(c.arg, []byte(content))
if c.errStr != "" {
if err == nil {
t.Fatalf("%s; expected error!", c.what)
}
if !strings.Contains(err.Error(), c.errStr) {
t.Fatalf("%s; expected err containing '%s', got '%v'",
c.what, c.errStr, err)
}
continue
}
if err != nil {
t.Fatalf("%s; unexpected error %v", c.what, err)
}
checkNode(t, c.what, f, c.name, len(content), false, c.path)
checkOsStat(t, c.what, f, f.Name(), len(content), false)
result, err := n.Find(c.arg)
if err != nil {
t.Fatalf("%s; unexpected find error %v", c.what, err)
}
if result != f {
t.Fatalf("%s; unexpected find result %v", c.what, result)
}
result, err = n.Find(filepath.Join("longer", "bogus"))
if err != nil {
t.Fatalf("%s; unexpected find error %v", c.what, err)
}
if result != nil {
t.Fatalf("%s; unexpected find result %v", c.what, result)
}
expectedFileCount++
fc := n.FileCount()
if fc != expectedFileCount {
t.Fatalf("expected file count %d, got %d",
expectedFileCount, fc)
}
}
}
func checkNode(
t *testing.T, what string, f *fsNode, name string,
size int, isDir bool, path string) {
if f.isNodeADir() != isDir {
t.Fatalf("%s; unexpected isNodeADir = %v", what, f.isNodeADir())
}
if f.Size() != int64(size) {
t.Fatalf("%s; unexpected size %d", what, f.Size())
}
if name != f.Name() {
t.Fatalf("%s; expected name '%s', got '%s'", what, name, f.Name())
}
if path != f.Path() {
t.Fatalf("%s; expected path '%s', got '%s'", what, path, f.Path())
}
}
func checkOsStat(
t *testing.T, what string, f File, name string,
size int, isDir bool) {
info, err := f.Stat()
if err != nil {
t.Fatalf("%s; unexpected stat error %v", what, err)
}
if info.IsDir() != isDir {
t.Fatalf("%s; unexpected info.isNodeADir = %v", what, info.IsDir())
}
if info.Size() != int64(size) {
t.Fatalf("%s; unexpected info.size %d", what, info.Size())
}
if info.Name() != name {
t.Fatalf("%s; expected name '%s', got info.Name '%s'", what, name, info.Name())
}
}
var bunchOfFiles = []struct {
path string
addAsDir bool
}{
{
path: filepath.Join("b", "e", "a", "c", "g"),
},
{
path: filepath.Join("z", "r", "a", "b", "g"),
},
{
path: filepath.Join("b", "q", "a", "c", "g"),
},
{
path: filepath.Join("b", "a", "a", "m", "g"),
addAsDir: true,
},
{
path: filepath.Join("b", "w"),
},
{
path: filepath.Join("b", "d", "a", "c", "m"),
},
{
path: filepath.Join("b", "d", "z"),
},
{
path: filepath.Join("b", "d", "y"),
},
{
path: filepath.Join("b", "d", "ignore", "c", "n"),
},
{
path: filepath.Join("b", "d", "x"),
},
{
path: filepath.Join("b", "d", "ignore", "c", "o"),
},
{
path: filepath.Join("b", "d", "ignore", "c", "m"),
},
{
path: filepath.Join("b", "d", "a", "c", "i"),
addAsDir: true,
},
{
path: filepath.Join("x"),
},
{
path: filepath.Join("y"),
},
{
path: filepath.Join("b", "d", "a", "c", "i", "beans"),
},
{
path: filepath.Join("b", "d", "a", "c", "r", "w"),
addAsDir: true,
},
{
path: filepath.Join("b", "d", "a", "c", "u"),
},
}
func makeLoadedFileTree(t *testing.T) *fsNode {
n := MakeEmptyDirInMemory()
var err error
expectedFileCount := 0
for _, item := range bunchOfFiles {
if item.addAsDir {
_, err = n.AddDir(item.path)
} else {
_, err = n.AddFile(item.path, []byte(content))
expectedFileCount++
}
if err != nil {
t.Fatalf("unexpected error %v", err)
}
}
fc := n.FileCount()
if fc != expectedFileCount {
t.Fatalf("expected file count %d, got %d",
expectedFileCount, fc)
}
return n
}
func TestWalkMe(t *testing.T) {
n := makeLoadedFileTree(t)
var actualPaths []string
err := n.WalkMe(func(path string, info os.FileInfo, err error) error {
if err != nil {
fmt.Printf("err '%v' at path %q\n", err, path)
return nil
}
if info.IsDir() {
if info.Name() == "ignore" {
return filepath.SkipDir
}
} else {
actualPaths = append(actualPaths, path)
}
return nil
})
if err != nil {
t.Fatalf("unexpected error %v", err)
}
var expectedPaths []string
for _, c := range bunchOfFiles {
if !c.addAsDir && !strings.Contains(c.path, "ignore") {
expectedPaths = append(expectedPaths, c.path)
}
}
sort.Strings(expectedPaths)
assertEqualStringSlices(t, expectedPaths, actualPaths, "testWalkMe")
}
func TestRemove(t *testing.T) {
n := makeLoadedFileTree(t)
orgCount := n.FileCount()
// Remove the "ignore" directory and everything below it.
path := filepath.Join("b", "d", "ignore")
result, err := n.Find(path)
if err != nil {
t.Fatalf("%s; unexpected error %v", path, err)
}
if result == nil {
t.Fatalf("%s; expected to find '%s'", path, path)
}
if !result.isNodeADir() {
t.Fatalf("%s; expected to find a directory", path)
}
err = result.Remove()
if err != nil {
t.Fatalf("%s; unable to remove: %v", path, err)
}
result, err = n.Find(path)
if err != nil {
// Just because it's gone doesn't mean error.
t.Fatalf("%s; unexpected error %v", path, err)
}
if result != nil {
t.Fatalf("%s; should not have been able to find '%s'", path, path)
}
// There were three files below "ignore".
orgCount -= 3
// Now drop one more for a total of four dropped.
result, _ = n.Find(filepath.Join("y"))
err = result.Remove()
if err != nil {
t.Fatalf("%s; unable to remove: %v", path, err)
}
orgCount -= 1
fc := n.FileCount()
if fc != orgCount {
t.Fatalf("expected file count %d, got %d",
orgCount, fc)
}
}
func TestExists(t *testing.T) {
n := makeLoadedFileTree(t)
path := filepath.Join("b", "d", "a")
if !n.Exists(path) {
t.Fatalf("expected existence at %s", path)
}
if !n.IsDir(path) {
t.Fatalf("expected directory at %s", path)
}
}
func TestRegExpGlob(t *testing.T) {
n := makeLoadedFileTree(t)
expected := []string{
filepath.Join("b", "d", "a", "c", "i", "beans"),
filepath.Join("b", "d", "a", "c", "m"),
filepath.Join("b", "d", "a", "c", "u"),
filepath.Join("b", "d", "ignore", "c", "m"),
filepath.Join("b", "d", "ignore", "c", "n"),
filepath.Join("b", "d", "ignore", "c", "o"),
filepath.Join("b", "d", "x"),
filepath.Join("b", "d", "y"),
filepath.Join("b", "d", "z"),
}
paths, err := n.RegExpGlob("b/d/*")
if err != nil {
t.Fatalf("glob error: %v", err)
}
assertEqualStringSlices(t, expected, paths, "glob test")
}
func TestGlob(t *testing.T) {
n := makeLoadedFileTree(t)
expected := []string{
filepath.Join("b", "d", "x"),
filepath.Join("b", "d", "y"),
filepath.Join("b", "d", "z"),
}
paths, err := n.Glob("b/d/*")
if err != nil {
t.Fatalf("glob error: %v", err)
}
assertEqualStringSlices(t, expected, paths, "glob test")
}
func assertEqualStringSlices(t *testing.T, expected, actual []string, message string) {
if len(expected) != len(actual) {
t.Fatalf(
"%s; unequal sizes; len(expected)=%d, len(actual)=%d\n%+v\n%+v\n",
message, len(expected), len(actual), expected, actual)
}
for i := range expected {
if expected[i] != actual[i] {
t.Fatalf(
"%s; unequal entries; expected=%s, actual=%s",
message, expected[i], actual[i])
}
}
}
func TestFind(t *testing.T) {
cases := []struct {
what string
arg string
expectDir bool
expectFile bool
errStr string
}{
{
what: "garbage",
arg: "///1(*&SA",
},
{
what: "simple",
arg: "bob",
},
{
what: "no directory",
arg: filepath.Join("b", "rrrrrr"),
},
{
what: "is a directory",
arg: filepath.Join("b", "d", "ignore"),
expectDir: true,
},
{
what: "longer, ending in file",
arg: filepath.Join("b", "d", "x"),
expectFile: true,
},
{
what: "moar longer, ending in file",
arg: filepath.Join("b", "d", "a", "c", "u"),
expectFile: true,
},
{
what: "directory",
arg: filepath.Join("b"),
expectDir: true,
},
{
// Querying for the empty string could
// 1) be an error,
// 2) return no result (and no error) as with
// any illegal and therefore non-existent
// file name,
// 3) return the node itself, like running
// 'ls' with no argument.
// Going with option 2 (no result, no error),
// since at this low level it makes more sense
// if the results for the empty string query
// differ from the results for the "." query.
what: "empty name",
arg: "",
},
{
what: "self dir",
arg: SelfDir,
expectDir: true,
},
{
what: "parent dir - doesn't exist",
arg: ParentDir,
},
{
what: "many parents - doesn't exist",
arg: filepath.Join(ParentDir, ParentDir, ParentDir),
},
}
n := makeLoadedFileTree(t)
for _, item := range cases {
result, err := n.Find(item.arg)
if item.errStr != "" {
if err == nil {
t.Fatalf("%s; expected error", item.what)
}
if !strings.Contains(err.Error(), item.errStr) {
t.Fatalf("%s; expected err containing '%s', got '%v'",
item.what, item.errStr, err)
}
continue
}
if err != nil {
t.Fatalf("%s; unexpected error: %v", item.what, err)
}
if result == nil {
if item.expectDir {
t.Fatalf(
"%s; expected to find directory '%s'", item.what, item.arg)
}
if item.expectFile {
t.Fatalf(
"%s; expected to find file '%s'", item.what, item.arg)
}
continue
}
if item.expectDir {
if !result.isNodeADir() {
t.Fatalf(
"%s; expected '%s' to be a directory", item.what, item.arg)
}
continue
}
if item.expectFile {
if result.isNodeADir() {
t.Fatalf("%s; expected '%s' to be a file", item.what, item.arg)
}
continue
}
t.Fatalf(
"%s; expected nothing for '%s', but got '%s'",
item.what, item.arg, result.Path())
}
}
func TestCleanedAbs(t *testing.T) {
cases := []struct {
what string
full string
cDir string
name string
errStr string
}{
{
what: "empty",
full: "",
errStr: "doesn't exist",
},
{
what: "simple",
full: "bob",
errStr: "'bob' doesn't exist",
},
{
what: "no directory",
full: filepath.Join("b", "rrrrrr"),
errStr: "'b/rrrrrr' doesn't exist",
},
{
what: "longer, ending in file",
full: filepath.Join("b", "d", "x"),
cDir: filepath.Join("b", "d"),
name: "x",
},
{
what: "moar longer, ending in file",
full: filepath.Join("b", "d", "a", "c", "u"),
cDir: filepath.Join("b", "d", "a", "c"),
name: "u",
},
{
what: "directory",
full: filepath.Join("b", "d"),
cDir: filepath.Join("b", "d"),
name: "",
},
}
n := makeLoadedFileTree(t)
for _, item := range cases {
cDir, name, err := n.CleanedAbs(item.full)
if item.errStr != "" {
if err == nil {
t.Fatalf("%s; expected error", item.what)
}
if !strings.Contains(err.Error(), item.errStr) {
t.Fatalf("%s; expected err containing '%s', got '%v'",
item.what, item.errStr, err)
}
continue
}
if err != nil {
t.Fatalf("%s; unexpected error: %v", item.what, err)
}
if cDir != ConfirmedDir(item.cDir) {
t.Fatalf("%s; expected cDir=%s, got '%s'", item.what, item.cDir, cDir)
}
if name != item.name {
t.Fatalf("%s; expected name=%s, got '%s'", item.what, item.name, name)
}
}
}

View File

@@ -1,12 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filesys
import "path/filepath"
// RootedPath returns a rooted path, e.g. "/foo/bar" as
// opposed to "foo/bar".
func RootedPath(elem ...string) string {
return separator + filepath.Join(elem...)
}

30
api/filesys/util.go Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filesys
import "path/filepath"
// RootedPath returns a rooted path, e.g. "/foo/bar" as
// opposed to "foo/bar".
func RootedPath(elem ...string) string {
return Separator + filepath.Join(elem...)
}
// StripTrailingSeps trims trailing filepath separators from input.
func StripTrailingSeps(s string) string {
k := len(s)
for k > 0 && s[k-1] == filepath.Separator {
k--
}
return s[:k]
}
// StripLeadingSeps trims leading filepath separators from input.
func StripLeadingSeps(s string) string {
k := 0
for k < len(s) && s[k] == filepath.Separator {
k++
}
return s[k:]
}

205
api/filesys/util_test.go Normal file
View File

@@ -0,0 +1,205 @@
package filesys_test
import (
"path/filepath"
"testing"
. "sigs.k8s.io/kustomize/api/filesys"
)
// Confirm behavior of filepath.Match
func TestFilePathMatch(t *testing.T) {
cases := []struct {
pattern string
path string
expected bool
}{
{
pattern: "*e*",
path: "hey",
expected: true,
},
{
pattern: "*e*",
path: "hay",
expected: false,
},
{
pattern: "*e*",
path: filepath.Join("h", "e", "y"),
expected: false,
},
{
pattern: "*/e/*",
path: filepath.Join("h", "e", "y"),
expected: true,
},
{
pattern: "h/e/*",
path: filepath.Join("h", "e", "y"),
expected: true,
},
{
pattern: "*/e/y",
path: filepath.Join("h", "e", "y"),
expected: true,
},
{
pattern: "*/*/*",
path: filepath.Join("h", "e", "y"),
expected: true,
},
{
pattern: "*/*/*",
path: filepath.Join("h", "e", "y", "there"),
expected: false,
},
{
pattern: "*/*/*/t*e",
path: filepath.Join("h", "e", "y", "there"),
expected: true,
},
}
for _, item := range cases {
match, err := filepath.Match(item.pattern, item.path)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if match != item.expected {
t.Fatalf("'%s' '%s' %v\n", item.pattern, item.path, match)
}
}
}
// Confirm behavior of filepath.Split
func TestFilePathSplit(t *testing.T) {
cases := []struct {
full string
dir string
file string
}{
{
full: "",
dir: "",
file: "",
},
{
full: SelfDir,
dir: "",
file: SelfDir,
},
{
full: "rabbit.jpg",
dir: "",
file: "rabbit.jpg",
},
{
full: "/beans",
dir: "/",
file: "beans",
},
{
full: "/home/foo/bar",
dir: "/home/foo/",
file: "bar",
},
{
full: "/usr/local/",
dir: "/usr/local/",
file: "",
},
{
full: "/usr//local//go",
dir: "/usr//local//",
file: "go",
},
}
for _, p := range cases {
dir, file := filepath.Split(p.full)
if dir != p.dir || file != p.file {
t.Fatalf(
"in '%s',\ngot dir='%s' (expected '%s'),\n got file='%s' (expected %s).",
p.full, dir, p.dir, file, p.file)
}
}
}
func TestStripTrailingSeps(t *testing.T) {
cases := []struct {
full string
rem string
}{
{
full: "foo",
rem: "foo",
},
{
full: "",
rem: "",
},
{
full: "foo/",
rem: "foo",
},
{
full: "foo///bar///",
rem: "foo///bar",
},
{
full: "/////",
rem: "",
},
{
full: "/",
rem: "",
},
}
for _, p := range cases {
dir := StripTrailingSeps(p.full)
if dir != p.rem {
t.Fatalf(
"in '%s', got dir='%s' (expected '%s')",
p.full, dir, p.rem)
}
}
}
func TestStripLeadingSeps(t *testing.T) {
cases := []struct {
full string
rem string
}{
{
full: "foo",
rem: "foo",
},
{
full: "",
rem: "",
},
{
full: "/foo",
rem: "foo",
},
{
full: "///foo///bar///",
rem: "foo///bar///",
},
{
full: "/////",
rem: "",
},
{
full: "/",
rem: "",
},
}
for _, p := range cases {
dir := StripLeadingSeps(p.full)
if dir != p.rem {
t.Fatalf(
"in '%s', got dir='%s' (expected '%s')",
p.full, dir, p.rem)
}
}
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/go-openapi/spec"
"github.com/pkg/errors"
"k8s.io/kube-openapi/pkg/common"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/resid"
@@ -78,7 +79,7 @@ func makeConfigFromApiMap(m nameToApiMap) (*builtinconfig.TransformerConfig, err
// openAPI definition once
// "x-kubernetes-group-version-kind" is available in CRD
func makeGvkFromTypeName(n string) resid.Gvk {
names := strings.Split(n, ".")
names := strings.Split(n, filesys.SelfDir)
kind := names[len(names)-1]
return resid.Gvk{Kind: kind}
}

View File

@@ -7,9 +7,10 @@ import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/loader"
. "sigs.k8s.io/kustomize/api/internal/accumulator"
"sigs.k8s.io/kustomize/api/internal/loadertest"
"sigs.k8s.io/kustomize/api/internal/plugins/builtinconfig"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/types"
@@ -135,15 +136,6 @@ If it is not set we generate a secret dynamically",
`
)
func makeLoader(t *testing.T) ifc.Loader {
ldr := loadertest.NewFakeLoader("/testpath")
err := ldr.AddFile("/testpath/crd.json", []byte(crdContent))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
return ldr
}
func TestLoadCRDs(t *testing.T) {
nbrs := []builtinconfig.NameBackReferences{
{
@@ -172,7 +164,14 @@ func TestLoadCRDs(t *testing.T) {
NameReference: nbrs,
}
actualTc, err := LoadConfigFromCRDs(makeLoader(t), []string{"crd.json"})
fSys := filesys.MakeFsInMemory()
fSys.WriteFile("/testpath/crd.json", []byte(crdContent))
ldr, err := loader.NewLoader(loader.RestrictionRootOnly, "/testpath", fSys)
if err != nil {
t.Fatalf("unexpected error:%v", err)
}
actualTc, err := LoadConfigFromCRDs(ldr, []string{"crd.json"})
if err != nil {
t.Fatalf("unexpected error:%v", err)
}

View File

@@ -0,0 +1,15 @@
FROM golang:1.11 AS build
ARG GO111MODULE=on
WORKDIR /go/src/sigs.k8s.io/kustomize/api/internal/crawl
COPY . /go/src/sigs.k8s.io/kustomize//api/internal/crawl
RUN go mod download
RUN CGO_ENABLED=0 go install -v ./cmd/crawler/crawler.go
FROM scratch
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /go/bin/crawler /
ENTRYPOINT ["/crawler"]
CMD []

View File

@@ -0,0 +1,93 @@
package main
import (
"context"
"fmt"
"net/http"
"os"
"time"
"sigs.k8s.io/kustomize/api/internal/crawl/crawler"
"sigs.k8s.io/kustomize/api/internal/crawl/crawler/github"
"sigs.k8s.io/kustomize/api/internal/crawl/doc"
"sigs.k8s.io/kustomize/api/internal/crawl/httpclient"
"sigs.k8s.io/kustomize/api/internal/crawl/index"
"github.com/gomodule/redigo/redis"
)
const (
githubAccessTokenVar = "GITHUB_ACCESS_TOKEN"
redisCacheURL = "REDIS_CACHE_URL"
redisKeyURL = "REDIS_KEY_URL"
retryCount = 3
)
func main() {
githubToken := os.Getenv(githubAccessTokenVar)
if githubToken == "" {
fmt.Printf("Must set the variable '%s' to make github requests.\n",
githubAccessTokenVar)
return
}
ctx := context.Background()
idx, err := index.NewKustomizeIndex(ctx)
if err != nil {
fmt.Printf("Could not create an index: %v\n", err)
return
}
cacheURL := os.Getenv(redisCacheURL)
query := []byte(`{ "query":{ "match_all":{} } }`)
it := idx.IterateQuery(query, 10000, 60*time.Second)
docs := make(crawler.CrawlSeed, 0)
for it.Next() {
for _, hit := range it.Value().Hits.Hits {
docs = append(docs, hit.Document.Copy())
}
}
if err := it.Err(); err != nil {
fmt.Printf("Error iterating: %v\n", err)
}
cache, err := redis.DialURL(cacheURL)
clientCache := &http.Client{}
if err != nil {
fmt.Printf("Error: redis could not make a connection: %v\n", err)
} else {
clientCache = httpclient.NewClient(cache)
}
ghCrawler := github.NewCrawler(githubToken, retryCount, clientCache,
github.QueryWith(
github.Filename("kustomization.yaml"),
github.Filename("kustomization.yml")),
)
crawler.CrawlFromSeed(ctx, docs, []crawler.Crawler{ghCrawler},
// Converter takes in a plain document and processes it for the
// index.
func(d *doc.Document) (crawler.CrawledDocument, error) {
kdoc := doc.KustomizationDocument{
Document: *d,
}
err := kdoc.ParseYAML()
return &kdoc, err
},
// IndexFunc updates the value in the index.
func(cdoc crawler.CrawledDocument, crwlr crawler.Crawler) error {
switch d := cdoc.(type) {
case *doc.KustomizationDocument:
fmt.Println("Inserting: ", d.ID(), d)
_, err := idx.Put(d.ID(), d)
return err
default:
return fmt.Errorf("type %T not supported", d)
}
},
)
}

View File

@@ -0,0 +1,2 @@
<ADD YOUR GITHUB PERSONAL ACCESS TOKEN HERE WITHOUT A TRAILING NEWLINE>
Run: printf "<your-token>" > github_api_secret.txt

View File

@@ -5,7 +5,9 @@ configmapGenerator:
- name: crawler-http-cache
literals:
- redis-cache-url="redis://redis-http-cache:6379"
- name: redis-keystore
literals:
- keystore-url="redis://redis-docs-keystore:6379"
secretGenerator:
- name: github-access-token

View File

@@ -12,6 +12,7 @@ spec:
containers:
- name: crawler
image: gcr.io/kustomize-search/crawler:latest
imagePullPolicy: Always
env:
- name: GITHUB_ACCESS_TOKEN
valueFrom:

View File

@@ -9,6 +9,7 @@ spec:
containers:
- name: crawler
image: gcr.io/kustomize-search/crawler:latest
imagePullPolicy: Always
env:
- name: GITHUB_ACCESS_TOKEN
valueFrom:

View File

@@ -0,0 +1,43 @@
apiVersion: elasticsearch.cloud.google.com/v1alpha1
kind: ESCluster
metadata:
name: esbasic
spec:
plugin:
pluginList:
- repository-gcs
- ingest-user-agent
- ingest-geoip
config:
env:
example: test
nodegroups:
- name: di
replicas: 2
data: true
ingest: true
config:
jvm:
- Djava.net.preferIPv4Stack=true
- Xms2g
- Xmx2g
es:
path.repo: '["/tmp/es_backup_basic"]'
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
es/nodegroup: di
resources:
requests:
memory: 3Gi
limits:
memory: 3Gi
- name: m
replicas: 2
master: true
config:
es:
path.repo: '["/tmp/es_backup_basic"]'

View File

@@ -17,14 +17,11 @@ spec:
containers:
- name: kustomize-search
image: gcr.io/kustomize-search/backend:latest
imagePullPolicy: Always
livenessProbe:
httpGet:
path: /liveness
port: backend-port
readinessProbe:
httpGet:
path: /readiness
port: backend-port
ports:
- name: backend-port
containerPort: 8080

View File

@@ -17,6 +17,7 @@ spec:
containers:
- name: frontend
image: gcr.io/kustomize-search/frontend:latest
imagePullPolicy: Always
ports:
- name: frontend-port
containerPort: 80

View File

@@ -102,11 +102,9 @@ func CrawlFromSeed(ctx context.Context, seed CrawlSeed,
}
doCrawl := func(docsPtr *CrawlSeed) {
for len(*docsPtr) > 0 {
back := len(*docsPtr) - 1
next := (*docsPtr)[back]
*docsPtr = (*docsPtr)[:back]
n := len(*docsPtr)
for i := 0; i < n; i++ {
next := (*docsPtr)[i]
match := findMatch(next)
if match == nil {
logIfErr(fmt.Errorf(
@@ -114,24 +112,28 @@ func CrawlFromSeed(ctx context.Context, seed CrawlSeed,
continue
}
logger.Println("Crawling ", next.RepositoryURL, next.FilePath)
err := match.FetchDocument(ctx, next)
logIfErr(err)
// If there was no change or there is an error, we don't have
// to branch out, since the dependencies are already in the
// index, or we cannot find the document.
if err != nil || next.WasCached() {
if next.WasCached() {
logger.Println(next.RepositoryURL, next.FilePath, "is cached already")
}
continue
}
logIfErr(match.SetCreated(ctx, next))
cdoc, err := conv(next)
logIfErr(err)
if err != nil {
continue
}
addBranches(cdoc, match)
}
}
// Exploit seed to update bulk of corpus.
logger.Printf("updating %d documents from seed\n", len(seed))
doCrawl(&seed)

View File

@@ -11,8 +11,8 @@ import (
"testing"
"time"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/internal/crawl/doc"
"sigs.k8s.io/kustomize/api/konfig"
)
const (
@@ -29,10 +29,10 @@ type testCrawler struct {
}
func (c testCrawler) Match(d *doc.Document) bool {
return d != nil && strings.HasPrefix(d.ID(), c.matchPrefix)
return d != nil
}
func (c testCrawler) FetchDocument(ctx context.Context, d *doc.Document) error {
func (c testCrawler) FetchDocument(_ context.Context, d *doc.Document) error {
if i, ok := c.lukp[d.ID()]; ok {
d.DocumentData = c.docs[i].DocumentData
return nil
@@ -51,7 +51,7 @@ func (c testCrawler) FetchDocument(ctx context.Context, d *doc.Document) error {
d, c.matchPrefix)
}
func (c testCrawler) SetCreated(ctx context.Context, d *doc.Document) error {
func (c testCrawler) SetCreated(_ context.Context, d *doc.Document) error {
d.CreationTime = &time.Time{}
return nil
}
@@ -71,7 +71,7 @@ func newCrawler(matchPrefix string, err error,
}
// Crawl implements the Crawler interface for testing.
func (c testCrawler) Crawl(ctx context.Context,
func (c testCrawler) Crawl(_ context.Context,
output chan<- CrawledDocument) error {
for i, d := range c.docs {

View File

@@ -16,11 +16,11 @@ import (
"strings"
"time"
"sigs.k8s.io/kustomize/api/internal/git"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/internal/crawl/crawler"
"sigs.k8s.io/kustomize/api/internal/crawl/doc"
"sigs.k8s.io/kustomize/api/internal/crawl/httpclient"
"sigs.k8s.io/kustomize/api/internal/git"
"sigs.k8s.io/kustomize/api/konfig"
)
var logger = log.New(os.Stdout, "Github Crawler: ",
@@ -34,11 +34,11 @@ type githubCrawler struct {
type GhClient struct {
RequestConfig
retryCount uint64
client *http.Client
retryCount uint64
client *http.Client
accessToken string
}
/*
func NewCrawler(accessToken string, retryCount uint64, client *http.Client,
query Query) githubCrawler {
@@ -47,14 +47,13 @@ func NewCrawler(accessToken string, retryCount uint64, client *http.Client,
retryCount: retryCount,
client: client,
RequestConfig: RequestConfig{
perPage: githubMaxPageSize,
accessToken: accessToken,
perPage: githubMaxPageSize,
},
accessToken: accessToken,
},
query: query,
}
}
*/
// Implements crawler.Crawler.
func (gc githubCrawler) Crawl(
@@ -64,6 +63,7 @@ func (gc githubCrawler) Crawl(
RequestConfig: gc.client.RequestConfig,
client: &http.Client{Timeout: gc.client.client.Timeout},
retryCount: gc.client.retryCount,
accessToken: gc.client.accessToken,
}
// Since Github returns a max of 1000 results per query, we can use
@@ -93,7 +93,7 @@ func (gc githubCrawler) Crawl(
return nil
}
func (gc githubCrawler) FetchDocument(ctx context.Context, d *doc.Document) error {
func (gc githubCrawler) FetchDocument(_ context.Context, d *doc.Document) error {
repoURL := d.RepositoryURL + "/" + d.FilePath + "?ref=" + d.DefaultBranch
repoSpec, err := git.NewRepoSpecFromUrl(repoURL)
if err != nil {
@@ -129,12 +129,16 @@ func (gc githubCrawler) FetchDocument(ctx context.Context, d *doc.Document) erro
continue
}
}
return fmt.Errorf("file not found: %s", url)
return fmt.Errorf("file not found: %s, error: %v", url, err)
}
func (gc githubCrawler) SetCreated(ctx context.Context, d *doc.Document) error {
fs := GhFileSpec{}
fs.Repository.FullName = d.RepositoryURL + "/" + d.FilePath
func (gc githubCrawler) SetCreated(_ context.Context, d *doc.Document) error {
fs := GhFileSpec{
Path: d.FilePath,
Repository: GitRepository{
FullName: d.RepositoryFullName(),
},
}
creationTime, err := gc.client.GetFileCreationTime(fs)
if err != nil {
return err
@@ -185,11 +189,13 @@ func processQuery(ctx context.Context, gcl GhClient, query string,
for _, file := range page.Parsed.Items {
k, err := kustomizationResultAdapter(gcl, file)
if err != nil {
logger.Printf("kustomizationResultAdapter failed: %v", err)
errs = append(errs, err)
errorCnt++
continue
}
output <- k
if k != nil {
output <- k
}
totalCnt++
}
@@ -224,6 +230,18 @@ func kustomizationResultAdapter(gcl GhClient, k GhFileSpec) (
RepositoryURL: k.Repository.URL,
},
}
logger.Printf("Set the creationTime field")
creationTime, err := gcl.GetFileCreationTime(k)
if err != nil {
logger.Printf("GetFileCreationTime failed: %v", err)
return &d, err
}
d.CreationTime = &creationTime
if err := d.ParseYAML(); err != nil {
logger.Printf("ParseYAML failed: %v", err)
return &d, err
}
return &d, nil
}
@@ -410,13 +428,15 @@ func (e multiError) Error() string {
return strings.Join(strs, "\n")
}
type GitRepository struct {
API string `json:"url,omitempty"`
URL string `json:"html_url,omitempty"`
FullName string `json:"full_name,omitempty"`
}
type GhFileSpec struct {
Path string `json:"path,omitempty"`
Repository struct {
API string `json:"url,omitempty"`
URL string `json:"html_url,omitempty"`
FullName string `json:"full_name,omitempty"`
} `json:"repository,omitempty"`
Path string `json:"path,omitempty"`
Repository GitRepository `json:"repository,omitempty"`
}
type githubResponse struct {
@@ -534,10 +554,20 @@ func (gcl GhClient) GetRawUserContent(query string) (*http.Response, error) {
return gcl.getWithRetry(query)
}
func (gcl GhClient) Do(query string) (*http.Response, error) {
req, err := http.NewRequest("GET", query, nil)
if err != nil {
return nil, err
}
req.Header.Add("Authorization", fmt.Sprintf("token %s", gcl.accessToken))
return gcl.client.Do(req)
}
func (gcl GhClient) getWithRetry(
query string) (resp *http.Response, err error) {
resp, err = gcl.client.Get(query)
resp, err = gcl.Do(query)
retryCount := gcl.retryCount
for err == nil &&
@@ -556,7 +586,7 @@ func (gcl GhClient) getWithRetry(
logger.Printf("waiting %d seconds before retrying\n", i)
time.Sleep(time.Second * time.Duration(i))
retryCount--
resp, err = gcl.client.Get(query)
resp, err = gcl.Do(query)
}
if err != nil {

View File

@@ -7,10 +7,11 @@ import (
)
const (
perPageArg = "per_page"
accessTokenArg = "access_token"
perPageArg = "per_page"
)
const githubMaxPageSize = 100
// Implementation detail, not important to external API.
type queryField struct {
name string
@@ -96,15 +97,7 @@ func Path(p string) queryField {
// - CommitsRequests: asks Github to list commits made one a file. Useful to
// determine the date of a file.
type RequestConfig struct {
perPage uint64
accessToken string
}
func NewRequestConfig(perPage uint64, accessToken string) RequestConfig {
return RequestConfig{
perPage: perPage,
accessToken: accessToken,
}
perPage uint64
}
// CodeSearchRequestWith given a list of query parameters that specify the
@@ -139,9 +132,6 @@ func (rc RequestConfig) CommitsRequest(fullRepoName, path string) string {
func (rc RequestConfig) makeRequest(path string, query Query) request {
vals := url.Values{}
if rc.accessToken != "" {
vals.Set(accessTokenArg, rc.accessToken)
}
vals.Set(perPageArg, fmt.Sprint(rc.perPage))
return request{
@@ -183,7 +173,7 @@ func (r request) URL() string {
if encoded == "" && query != "" {
sep = "?"
}
r.url.RawQuery = encoded + sep + query
r.url.RawQuery = query + sep + encoded
return r.url.String()
}

View File

@@ -68,8 +68,7 @@ func TestQueryType(t *testing.T) {
func TestGithubSearchQuery(t *testing.T) {
const (
accessToken = "random_token"
perPage = 100
perPage = 100
)
testCases := []struct {
@@ -83,8 +82,7 @@ func TestGithubSearchQuery(t *testing.T) {
}{
{
rc: RequestConfig{
perPage: perPage,
accessToken: accessToken,
perPage: perPage,
},
codeQuery: Query{
Filename("kustomization.yaml"),
@@ -94,13 +92,13 @@ func TestGithubSearchQuery(t *testing.T) {
path: "examples/helloWorld/kustomization.yaml",
expectedCodeQuery: "https://api.github.com/search/code?" +
"access_token=random_token&order=desc&per_page=100&sort=indexed&q=filename:kustomization.yaml+size:64..128",
"q=filename:kustomization.yaml+size:64..128&order=desc&per_page=100&sort=indexed",
expectedContentsQuery: "https://api.github.com/repos/kubernetes-sigs/kustomize/contents/" +
"examples/helloWorld/kustomization.yaml?access_token=random_token&per_page=100",
"examples/helloWorld/kustomization.yaml?per_page=100",
expectedCommitsQuery: "https://api.github.com/repos/kubernetes-sigs/kustomize/commits?" +
"access_token=random_token&per_page=100&q=path:examples/helloWorld/kustomization.yaml",
"q=path:examples/helloWorld/kustomization.yaml&per_page=100",
},
}

View File

@@ -43,6 +43,12 @@ type KustomizationDocument struct {
type set map[string]struct{}
func (doc *KustomizationDocument) String() string {
return fmt.Sprintf("%s %s %s %v %v %v len(identifiers):%v len(values):%v",
doc.RepositoryURL, doc.FilePath, doc.DefaultBranch, doc.CreationTime,
doc.IsSame, doc.Kinds, len(doc.Identifiers), len(doc.Values))
}
// Implements the CrawlerDocument interface.
func (doc *KustomizationDocument) GetResources() ([]*Document, error) {
isResource := true
@@ -117,6 +123,8 @@ func (doc *KustomizationDocument) ParseYAML() error {
identifierSet := make(set)
valueSet := make(set)
kindSet := make(set)
getKind := func(m map[string]interface{}) string {
const defaultStr = "Kustomization"
kind, ok := m["kind"]
@@ -135,10 +143,14 @@ func (doc *KustomizationDocument) ParseYAML() error {
}
for _, contents := range ks {
doc.Kinds = append(doc.Kinds, getKind(contents))
kindSet[getKind(contents)] = struct{}{}
createFlatStructure(identifierSet, valueSet, contents)
}
for val := range kindSet {
doc.Kinds = append(doc.Kinds, val)
}
for val := range valueSet {
doc.Values = append(doc.Values, val)
}

View File

@@ -121,6 +121,38 @@ metadata:
kind: Custom
metadata:
name: app-crd
`,
},
{
identifiers: []string{
"kind",
"metadata",
"metadata:name",
},
values: []string{
"kind=Deployment",
"kind=Service",
"metadata:name=app1",
"metadata:name=app2",
},
kinds: []string{
"Deployment",
"Service",
},
filepath: "resources.yaml",
yaml: `
---
kind: Deployment
metadata:
name: app1
---
kind: Deployment
metadata:
name: app2
---
kind: Service
metadata:
name: app1
`,
},
}

View File

@@ -1,7 +1,10 @@
package doc
import (
"crypto/sha256"
"fmt"
"path"
"strings"
"time"
"sigs.k8s.io/kustomize/api/internal/git"
@@ -21,6 +24,17 @@ func (doc *Document) GetDocument() *Document {
return doc
}
func (doc *Document) Copy() *Document {
return &Document{
RepositoryURL: doc.RepositoryURL,
FilePath: doc.FilePath,
DefaultBranch: doc.DefaultBranch,
DocumentData: doc.DocumentData,
CreationTime: doc.CreationTime,
IsSame: doc.IsSame,
}
}
// Implements the CrawlerDocument interface.
func (doc *Document) WasCached() bool {
return doc.IsSame
@@ -53,6 +67,22 @@ func (doc *Document) FromRelativePath(newFile string) (Document, error) {
}
func (doc *Document) ID() string {
return doc.RepositoryURL + "/" +
doc.DefaultBranch + "/" + doc.FilePath
sum := sha256.Sum256([]byte(strings.Join(
[]string{
doc.RepositoryURL,
doc.DefaultBranch,
doc.FilePath,
},
"---|---")))
return fmt.Sprintf("%x", sum)
}
func (doc *Document) RepositoryFullName() string {
doc.RepositoryURL = strings.TrimRight(doc.RepositoryURL, "/")
sections := strings.Split(doc.RepositoryURL, "/")
l := len(sections)
if l < 2 {
return doc.RepositoryURL
}
return path.Join(sections[l-2], sections[l-1])
}

View File

@@ -62,3 +62,44 @@ func TestFromRelativePath(t *testing.T) {
}
}
}
func TestDocument_RepositoryFullName(t *testing.T) {
testCases := []struct {
doc Document
expectedRepositoryFullName string
}{
{
doc: Document{
RepositoryURL: "https://github.com/user/repo",
},
expectedRepositoryFullName: "user/repo",
},
{
doc: Document{
RepositoryURL: "https://github.com//user/repo////",
},
expectedRepositoryFullName: "user/repo",
},
{
doc: Document{
RepositoryURL: "repo/",
},
expectedRepositoryFullName: "repo",
},
{
doc: Document{
RepositoryURL: "",
},
expectedRepositoryFullName: "",
},
}
for _, tc := range testCases {
returnedRepositoryFullName := tc.doc.RepositoryFullName()
if returnedRepositoryFullName != tc.expectedRepositoryFullName {
t.Errorf("RepositoryFullName expected %s, got %s",
tc.expectedRepositoryFullName,
returnedRepositoryFullName)
}
}
}

View File

@@ -13,6 +13,40 @@ import (
"github.com/elastic/go-elasticsearch/v6/esapi"
)
const IndexConfig = `
{
"mappings": {
"_doc": {
"properties": {
"repositoryUrl": {
"type": "keyword"
},
"filePath": {
"type": "keyword"
},
"defaultBranch": {
"type": "keyword"
},
"document": {
"type": "text"
},
"creationTime": {
"type": "date"
},
"kinds": {
"type": "text"
},
"identifiers": {
"type": "text"
},
"values": {
"type": "text"
}
}
}
}
}`
// TODO(damienr74) Split index into reader and writer?
type index struct {
ctx context.Context
@@ -118,21 +152,19 @@ func (idx *index) UpdateSetting(settings []byte) error {
res, err, ignoreResponseBody)
}
// Create an index providing both the mappings and the settings.
func (idx *index) CreateIndex(mappings []byte, settings []byte) error {
request := byteJoin(`{ "mappings":`, mappings, `, "settings":`, settings, `}`)
// Create an index providing the config for both the mappings and the settings.
func (idx *index) CreateIndex(config []byte) error {
op := idx.client.Indices.Create
res, err := op(
idx.name,
op.WithBody(bytes.NewReader(request)),
op.WithBody(bytes.NewReader(config)),
op.WithContext(idx.ctx),
op.WithHuman(),
op.WithPretty(),
op.WithIncludeTypeName(true),
)
return idx.responseErrorOrNil(
fmt.Sprintf("could not create index with config '%s'", request),
fmt.Sprintf("could not create index with config '%s'", config),
res, err, ignoreResponseBody)
}

View File

@@ -96,6 +96,24 @@ func NewKustomizeIndex(ctx context.Context) (*KustomizeIndex, error) {
if err != nil {
return nil, err
}
indicesExistsOp := idx.client.Indices.Exists
resp, err := indicesExistsOp([]string{"kustomize"},
indicesExistsOp.WithContext(idx.ctx),
indicesExistsOp.WithPretty())
if err != nil {
return nil, err
}
if resp.StatusCode == 200 {
fmt.Printf("The kustomize index already exists\n")
} else {
fmt.Printf("Creating the kustomize index\n")
if err := idx.CreateIndex([]byte(IndexConfig)); err != nil {
return nil, err
}
}
return &KustomizeIndex{idx}, nil
}

View File

@@ -74,8 +74,28 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error {
cmd.Dir = repoSpec.Dir.String()
err = cmd.Run()
if err != nil {
log.Printf("Error performing git fetch: %s", out.String())
return errors.Wrapf(err, "trouble fetching %s", repoSpec.Ref)
cmd = exec.Command(
gitProgram,
"pull",
"origin",
"master")
var out bytes.Buffer
cmd.Stdout = &out
cmd.Dir = repoSpec.Dir.String()
err := cmd.Run()
if err != nil {
return errors.Wrapf(err, "trouble pulling %s", repoSpec.OrgRepo)
}
if repoSpec.Ref == "" {
repoSpec.Ref = "master"
}
cmd = exec.Command(gitProgram, "checkout", repoSpec.Ref)
cmd.Dir = repoSpec.Dir.String()
err = cmd.Run()
if err != nil {
return errors.Wrapf(
err, "trouble checking out href %s", repoSpec.Ref)
}
}
cmd = exec.Command(

View File

@@ -1,76 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package loadertest holds a fake for the Loader interface.
package loadertest
import (
"log"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/loader"
)
// FakeLoader encapsulates the delegate Loader and the fake file system.
type FakeLoader struct {
fs filesys.FileSystem
delegate ifc.Loader
}
// NewFakeLoader returns a Loader that uses a fake filesystem.
// The loader will be restricted to root only.
// The initialDir argument should be an absolute file path.
func NewFakeLoader(initialDir string) FakeLoader {
return NewFakeLoaderWithRestrictor(
loader.RestrictionRootOnly, initialDir)
}
// NewFakeLoaderWithRestrictor returns a Loader that
// uses a fake filesystem.
// The initialDir argument should be an absolute file path.
func NewFakeLoaderWithRestrictor(
lr loader.LoadRestrictorFunc, initialDir string) FakeLoader {
// Create fake filesystem and inject it into initial Loader.
fSys := filesys.MakeFsInMemory()
fSys.Mkdir(initialDir)
ldr, err := loader.NewLoader(lr, initialDir, fSys)
if err != nil {
log.Fatalf("Unable to make loader: %v", err)
}
return FakeLoader{fs: fSys, delegate: ldr}
}
// AddFile adds a fake file to the file system.
func (f FakeLoader) AddFile(fullFilePath string, content []byte) error {
return f.fs.WriteFile(fullFilePath, content)
}
// AddDirectory adds a fake directory to the file system.
func (f FakeLoader) AddDirectory(fullDirPath string) error {
return f.fs.Mkdir(fullDirPath)
}
// Root delegates.
func (f FakeLoader) Root() string {
return f.delegate.Root()
}
// New creates a new loader from a new root.
func (f FakeLoader) New(newRoot string) (ifc.Loader, error) {
l, err := f.delegate.New(newRoot)
if err != nil {
return nil, err
}
return FakeLoader{fs: f.fs, delegate: l}, nil
}
// Load delegates.
func (f FakeLoader) Load(location string) ([]byte, error) {
return f.delegate.Load(location)
}
// Cleanup delegates.
func (f FakeLoader) Cleanup() error {
return f.delegate.Cleanup()
}

View File

@@ -7,21 +7,30 @@ import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/api/internal/loadertest"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/types"
)
func TestLoadDefaultConfigsFromFiles(t *testing.T) {
ldr := loadertest.NewFakeLoader("/app")
ldr.AddFile("/app/config.yaml", []byte(`
fSys := filesys.MakeFsInMemory()
err := fSys.WriteFile("config.yaml", []byte(`
namePrefix:
- path: nameprefix/path
kind: SomeKind
`))
tcfg, err := loadDefaultConfig(ldr, []string{"/app/config.yaml"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
t.Fatal(err)
}
ldr, err := loader.NewLoader(
loader.RestrictionRootOnly, filesys.Separator, fSys)
if err != nil {
t.Fatal(err)
}
tCfg, err := loadDefaultConfig(ldr, []string{"config.yaml"})
if err != nil {
t.Fatal(err)
}
expected := &TransformerConfig{
NamePrefix: []types.FieldSpec{
@@ -31,7 +40,7 @@ namePrefix:
},
},
}
if !reflect.DeepEqual(tcfg, expected) {
t.Fatalf("expected %v\n but go6t %v\n", expected, tcfg)
if !reflect.DeepEqual(tCfg, expected) {
t.Fatalf("expected %v\n but go6t %v\n", expected, tCfg)
}
}

View File

@@ -37,6 +37,16 @@ func DeterminePluginSrcRoot(fSys filesys.FileSystem) (string, error) {
"source directory", fSys, []konfig.NotedFunc{
{
Note: "relative to unit test",
F: func() string {
return filepath.Clean(
filepath.Join(
os.Getenv("PWD"),
"..", "..",
konfig.RelPluginHome))
},
},
{
Note: "relative to unit test (internal pkg)",
F: func() string {
return filepath.Clean(
filepath.Join(

View File

@@ -8,11 +8,12 @@ import (
"strings"
"testing"
"sigs.k8s.io/kustomize/api/internal/loadertest"
"sigs.k8s.io/kustomize/api/filesys"
. "sigs.k8s.io/kustomize/api/internal/plugins/execplugin"
"sigs.k8s.io/kustomize/api/internal/plugins/loader"
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
@@ -20,11 +21,20 @@ import (
)
func TestExecPluginConfig(t *testing.T) {
path := "/app"
fSys := filesys.MakeFsInMemory()
fSys.WriteFile("sed-input.txt", []byte(`
s/$FOO/foo/g
s/$BAR/bar/g
\ \ \
`))
ldr, err := fLdr.NewLoader(
fLdr.RestrictionRootOnly, filesys.Separator, fSys)
if err != nil {
t.Fatal(err)
}
rf := resmap.NewFactory(
resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl()), nil)
ldr := loadertest.NewFakeLoader(path)
v := valtest_test.MakeFakeValidator()
pluginConfig := rf.RF().FromMap(
map[string]interface{}{
@@ -36,15 +46,8 @@ func TestExecPluginConfig(t *testing.T) {
"argsOneLiner": "one two",
"argsFromFile": "sed-input.txt",
})
ldr.AddFile("/app/sed-input.txt", []byte(`
s/$FOO/foo/g
s/$BAR/bar/g
\ \ \
`))
p := NewExecPlugin(
loader.AbsolutePluginPath(
pLdr.AbsolutePluginPath(
konfig.DisabledPluginConfig(),
pluginConfig.OrgId()))
// Not checking to see if the plugin is executable,

View File

@@ -6,10 +6,11 @@ package loader_test
import (
"testing"
"sigs.k8s.io/kustomize/api/internal/loadertest"
"sigs.k8s.io/kustomize/api/filesys"
. "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
@@ -45,36 +46,33 @@ port: "12345"
)
func TestLoader(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
"builtin", "", "SecretGenerator")
tc.BuildGoPlugin(
"someteam.example.com", "v1", "SomeServiceGenerator")
th := kusttest_test.MakeEnhancedHarness(t).
BuildGoPlugin("builtin", "", "SecretGenerator").
BuildGoPlugin("someteam.example.com", "v1", "SomeServiceGenerator")
defer th.Reset()
rmF := resmap.NewFactory(resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl()), nil)
ldr := loadertest.NewFakeLoader("/foo")
fLdr, err := loader.NewLoader(
loader.RestrictionRootOnly,
filesys.Separator, filesys.MakeFsInMemory())
if err != nil {
t.Fatal(err)
}
c, err := konfig.EnabledPluginConfig()
if err != nil {
t.Fatal(err)
}
pLdr := NewLoader(c, rmF)
if pLdr == nil {
t.Fatal("expect non-nil loader")
}
m, err := rmF.NewResMapFromBytes([]byte(
someServiceGenerator + "---\n" + secretGenerator))
if err != nil {
t.Fatal(err)
}
_, err = pLdr.LoadGenerators(ldr, valtest_test.MakeFakeValidator(), m)
_, err = pLdr.LoadGenerators(
fLdr, valtest_test.MakeFakeValidator(), m)
if err != nil {
t.Fatal(err)
}

View File

@@ -1,60 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
import (
"testing"
. "sigs.k8s.io/kustomize/api/internal/target"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func TestTargetMustHaveKustomizationFile(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th.WriteF("/app/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: aService
`)
th.WriteF("/app/deeper/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: anotherService
`)
_, err := th.MakeKustTargetOrErr()
if err == nil {
t.Fatalf("expected an error")
}
if !IsMissingKustomizationFileError(err) {
t.Fatalf("unexpected error: %q", err)
}
}
func TestResourceDirectoryMustHaveKustomizationFile(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th.WriteK("/app", `
resources:
- base
`)
th.WriteF("/app/base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: myService
spec:
selector:
backend: bungie
ports:
- port: 7002
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
if err == nil {
t.Fatalf("expected an error")
}
if !IsMissingKustomizationFileError(err) {
t.Fatalf("unexpected error: %q", err)
}
}

View File

@@ -0,0 +1,48 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target
import (
"fmt"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/konfig"
)
type errMissingKustomization struct {
path string
}
func (e *errMissingKustomization) Error() string {
return fmt.Sprintf(
"unable to find one of %v in directory '%s'",
commaOr(quoted(konfig.RecognizedKustomizationFileNames())),
e.path)
}
func IsMissingKustomizationFileError(err error) bool {
_, ok := err.(*errMissingKustomization)
if ok {
return true
}
_, ok = errors.Cause(err).(*errMissingKustomization)
return ok
}
func NewErrMissingKustomization(p string) *errMissingKustomization {
return &errMissingKustomization{path: p}
}
func quoted(l []string) []string {
r := make([]string, len(l))
for i, v := range l {
r[i] = "'" + v + "'"
}
return r
}
func commaOr(q []string) string {
return strings.Join(q[:len(q)-1], ", ") + " or " + q[len(q)-1]
}

View File

@@ -1,8 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package target implements state for the set of all
// resources to customize.
package target
import (
@@ -36,50 +34,43 @@ type KustTarget struct {
pLdr *loader.Loader
}
// NewKustTarget returns a new instance of KustTarget primed with a Loader.
// NewKustTarget returns a new instance of KustTarget.
func NewKustTarget(
ldr ifc.Loader,
validator ifc.Validator,
rFactory *resmap.Factory,
tFactory resmap.PatchFactory,
pLdr *loader.Loader) (*KustTarget, error) {
content, err := loadKustFile(ldr)
pLdr *loader.Loader) *KustTarget {
return &KustTarget{
ldr: ldr,
validator: validator,
rFactory: rFactory,
tFactory: tFactory,
pLdr: pLdr,
}
}
// Load attempts to load the target's kustomization file.
func (kt *KustTarget) Load() error {
content, err := loadKustFile(kt.ldr)
if err != nil {
return nil, err
return err
}
content = types.FixKustomizationPreUnmarshalling(content)
var k types.Kustomization
err = unmarshal(content, &k)
if err != nil {
return nil, err
return err
}
k.FixKustomizationPostUnmarshalling()
errs := k.EnforceFields()
if len(errs) > 0 {
return nil, fmt.Errorf(
return fmt.Errorf(
"Failed to read kustomization file under %s:\n"+
strings.Join(errs, "\n"), ldr.Root())
strings.Join(errs, "\n"), kt.ldr.Root())
}
return &KustTarget{
kustomization: &k,
ldr: ldr,
validator: validator,
rFactory: rFactory,
tFactory: tFactory,
pLdr: pLdr,
}, nil
}
func quoted(l []string) []string {
r := make([]string, len(l))
for i, v := range l {
r[i] = "'" + v + "'"
}
return r
}
func commaOr(q []string) string {
return strings.Join(q[:len(q)-1], ", ") + " or " + q[len(q)-1]
kt.kustomization = &k
return nil
}
func loadKustFile(ldr ifc.Loader) ([]byte, error) {
@@ -103,30 +94,6 @@ func loadKustFile(ldr ifc.Loader) ([]byte, error) {
}
}
type errMissingKustomization struct {
path string
}
func (e *errMissingKustomization) Error() string {
return fmt.Sprintf(
"unable to find one of %v in directory '%s'",
commaOr(quoted(konfig.RecognizedKustomizationFileNames())),
e.path)
}
func NewErrMissingKustomization(p string) *errMissingKustomization {
return &errMissingKustomization{path: p}
}
func IsMissingKustomizationFileError(err error) bool {
_, ok := err.(*errMissingKustomization)
if ok {
return true
}
_, ok = errors.Cause(err).(*errMissingKustomization)
return ok
}
func unmarshal(y []byte, o interface{}) error {
j, err := yaml.YAMLToJSON(y)
if err != nil {
@@ -137,8 +104,8 @@ func unmarshal(y []byte, o interface{}) error {
return dec.Decode(o)
}
// MakeCustomizedResMap creates a ResMap per kustomization instructions.
// The Resources in the returned ResMap are fully customized.
// MakeCustomizedResMap creates a fully customized ResMap
// per the instructions contained in its kustomiztion instance.
func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) {
return kt.makeCustomizedResMap(types.GarbageIgnore)
}
@@ -356,8 +323,9 @@ func (kt *KustTarget) accumulateResources(
func (kt *KustTarget) accumulateDirectory(
ra *accumulator.ResAccumulator, ldr ifc.Loader) error {
defer ldr.Cleanup()
subKt, err := NewKustTarget(
subKt := NewKustTarget(
ldr, kt.validator, kt.rFactory, kt.tFactory, kt.pLdr)
err := subKt.Load()
if err != nil {
return errors.Wrapf(
err, "couldn't make target for path '%s'", ldr.Root())

View File

@@ -5,23 +5,23 @@ package target_test
import (
"encoding/base64"
"fmt"
"strings"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/loadertest"
. "sigs.k8s.io/kustomize/api/internal/target"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
)
const (
kustomizationContent = `
// KustTarget is primarily tested in the krusty package with
// high level tests.
func TestMakeCustomizedResMap(t *testing.T) {
fSys := filesys.MakeFsInMemory()
th := kusttest_test.MakeHarnessWithFs(t, fSys)
th.WriteK("/whatever", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: foo-
@@ -54,33 +54,27 @@ patchesJson6902:
kind: Deployment
name: dply1
path: jsonpatch.json
`
deploymentContent = `
`)
th.WriteF("/whatever/deployment.yaml", `
apiVersion: apps/v1
metadata:
name: dply1
kind: Deployment
`
namespaceContent = `
`)
th.WriteF("/whatever/namespace.yaml", `
apiVersion: v1
kind: Namespace
metadata:
name: ns1
`
jsonpatchContent = `[
`)
th.WriteF("/whatever/jsonpatch.json", `[
{"op": "add", "path": "/spec/replica", "value": "3"}
]`
)
]`)
func TestResources(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/whatever")
th.WriteK("/whatever/", kustomizationContent)
th.WriteF("/whatever/deployment.yaml", deploymentContent)
th.WriteF("/whatever/namespace.yaml", namespaceContent)
th.WriteF("/whatever/jsonpatch.json", jsonpatchContent)
resFactory := resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl())
resources := []*resource.Resource{
th.RF().FromMapWithName("dply1", map[string]interface{}{
resFactory.FromMapWithName("dply1", map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
@@ -112,7 +106,7 @@ func TestResources(t *testing.T) {
},
},
}),
th.RF().FromMapWithName("ns1", map[string]interface{}{
resFactory.FromMapWithName("ns1", map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": map[string]interface{}{
@@ -125,7 +119,7 @@ func TestResources(t *testing.T) {
},
},
}),
th.RF().FromMapWithName("literalConfigMap",
resFactory.FromMapWithName("literalConfigMap",
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
@@ -144,7 +138,7 @@ func TestResources(t *testing.T) {
"DB_PASSWORD": "somepw",
},
}),
th.RF().FromMapWithName("secret",
resFactory.FromMapWithName("secret",
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
@@ -173,7 +167,8 @@ func TestResources(t *testing.T) {
}
}
actual, err := th.MakeKustTarget().MakeCustomizedResMap()
actual, err := makeKustTargetWithRf(
t, fSys, "/whatever", resFactory).MakeCustomizedResMap()
if err != nil {
t.Fatalf("unexpected Resources error %v", err)
}
@@ -182,265 +177,3 @@ func TestResources(t *testing.T) {
t.Fatalf("unexpected inequality: %v", err)
}
}
func TestKustomizationNotFound(t *testing.T) {
_, err := NewKustTarget(
loadertest.NewFakeLoader("/foo"),
valtest_test.MakeFakeValidator(), nil, nil, nil)
if err == nil {
t.Fatalf("expected an error")
}
if err.Error() !=
`unable to find one of 'kustomization.yaml', 'kustomization.yml' or 'Kustomization' in directory '/foo'` {
t.Fatalf("unexpected error: %q", err)
}
}
func TestResourceNotFound(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/whatever")
th.WriteK("/whatever", kustomizationContent)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
if err == nil {
t.Fatalf("Didn't get the expected error for an unknown resource")
}
if !strings.Contains(err.Error(), `cannot read file`) {
t.Fatalf("unexpected error: %q", err)
}
}
func findSecret(m resmap.ResMap) *resource.Resource {
for _, r := range m.Resources() {
if r.OrgId().Kind == "Secret" {
return r
}
}
return nil
}
func TestDisableNameSuffixHash(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/whatever")
th.WriteK("/whatever/", kustomizationContent)
th.WriteF("/whatever/deployment.yaml", deploymentContent)
th.WriteF("/whatever/namespace.yaml", namespaceContent)
th.WriteF("/whatever/jsonpatch.json", jsonpatchContent)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("unexpected Resources error %v", err)
}
secret := findSecret(m)
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "foo-secret-bar-9btc7bt4kb" {
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
th.WriteK("/whatever/",
strings.Replace(kustomizationContent,
"disableNameSuffixHash: false",
"disableNameSuffixHash: true", -1))
m, err = th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("unexpected Resources error %v", err)
}
secret = findSecret(m)
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "foo-secret-bar" { // No hash at end.
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
}
func TestIssue596AllowDirectoriesThatAreSubstringsOfEachOther(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlays/aws-sandbox2.us-east-1")
th.WriteK("/app/base", "")
th.WriteK("/app/overlays/aws", `
resources:
- ../../base
`)
th.WriteK("/app/overlays/aws-nonprod", `
resources:
- ../aws
`)
th.WriteK("/app/overlays/aws-sandbox2.us-east-1", `
resources:
- ../aws-nonprod
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
th.AssertActualEqualsExpected(m, "")
}
// To simplify tests, these vars specified in alphabetical order.
var someVars = []types.Var{
{
Name: "AWARD",
ObjRef: types.Target{
APIVersion: "v7",
Gvk: resid.Gvk{Kind: "Service"},
Name: "nobelPrize"},
FieldRef: types.FieldSelector{FieldPath: "some.arbitrary.path"},
},
{
Name: "BIRD",
ObjRef: types.Target{
APIVersion: "v300",
Gvk: resid.Gvk{Kind: "Service"},
Name: "heron"},
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
},
{
Name: "FRUIT",
ObjRef: types.Target{
Gvk: resid.Gvk{Kind: "Service"},
Name: "apple"},
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
},
{
Name: "VEGETABLE",
ObjRef: types.Target{
Gvk: resid.Gvk{Kind: "Leafy"},
Name: "kale"},
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
},
}
func TestGetAllVarsSimple(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th.WriteK("/app", `
vars:
- name: AWARD
objref:
kind: Service
name: nobelPrize
apiVersion: v7
fieldref:
fieldpath: some.arbitrary.path
- name: BIRD
objref:
kind: Service
name: heron
apiVersion: v300
`)
ra, err := th.MakeKustTarget().AccumulateTarget()
if err != nil {
t.Fatalf("Err: %v", err)
}
vars := ra.Vars()
if len(vars) != 2 {
t.Fatalf("unexpected size %d", len(vars))
}
for i := range vars[:2] {
// By using Var.DeepEqual, we are protecting the code
// from a potential invocation of vars[i].ObjRef.GVK()
// during AccumulateTarget
if !vars[i].DeepEqual(someVars[i]) {
t.Fatalf("unexpected var[%d]:\n %v\n %v", i, vars[i], someVars[i])
}
}
}
func TestGetAllVarsNested(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlays/o2")
th.WriteK("/app/base", `
vars:
- name: AWARD
objref:
kind: Service
name: nobelPrize
apiVersion: v7
fieldref:
fieldpath: some.arbitrary.path
- name: BIRD
objref:
kind: Service
name: heron
apiVersion: v300
`)
th.WriteK("/app/overlays/o1", `
vars:
- name: FRUIT
objref:
kind: Service
name: apple
resources:
- ../../base
`)
th.WriteK("/app/overlays/o2", `
vars:
- name: VEGETABLE
objref:
kind: Leafy
name: kale
resources:
- ../o1
`)
ra, err := th.MakeKustTarget().AccumulateTarget()
if err != nil {
t.Fatalf("Err: %v", err)
}
vars := ra.Vars()
if len(vars) != 4 {
for i, v := range vars {
fmt.Printf("%v: %v\n", i, v)
}
t.Fatalf("expected 4 vars, got %d", len(vars))
}
for i := range vars {
// By using Var.DeepEqual, we are protecting the code
// from a potential invocation of vars[i].ObjRef.GVK()
// during AccumulateTarget
if !vars[i].DeepEqual(someVars[i]) {
t.Fatalf("unexpected var[%d]:\n %v\n %v", i, vars[i], someVars[i])
}
}
}
func TestVarCollisionsForbidden(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlays/o2")
th.WriteK("/app/base", `
vars:
- name: AWARD
objref:
kind: Service
name: nobelPrize
apiVersion: v7
fieldref:
fieldpath: some.arbitrary.path
- name: BIRD
objref:
kind: Service
name: heron
apiVersion: v300
`)
th.WriteK("/app/overlays/o1", `
vars:
- name: AWARD
objref:
kind: Service
name: academy
resources:
- ../../base
`)
th.WriteK("/app/overlays/o2", `
vars:
- name: VEGETABLE
objref:
kind: Leafy
name: kale
resources:
- ../o1
`)
_, err := th.MakeKustTarget().AccumulateTarget()
if err == nil {
t.Fatalf("expected var collision")
}
if !strings.Contains(err.Error(),
"var 'AWARD' already encountered") {
t.Fatalf("unexpected error: %v", err)
}
}

View File

@@ -0,0 +1,51 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
import (
"testing"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/internal/k8sdeps/transformer"
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/internal/target"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
)
func makeKustTarget(
t *testing.T,
fSys filesys.FileSystem,
root string) *target.KustTarget {
return makeKustTargetWithRf(
t, fSys, root,
resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()))
}
func makeKustTargetWithRf(
t *testing.T,
fSys filesys.FileSystem,
root string,
resFact *resource.Factory) *target.KustTarget {
rf := resmap.NewFactory(resFact, transformer.NewFactoryImpl())
pc := konfig.DisabledPluginConfig()
ldr, err := fLdr.NewLoader(fLdr.RestrictionRootOnly, root, fSys)
if err != nil {
t.Fatal(err)
}
kt := target.NewKustTarget(
ldr,
valtest_test.MakeFakeValidator(),
rf,
transformer.NewFactoryImpl(),
pLdr.NewLoader(pc, rf))
if err = kt.Load(); err != nil {
t.Fatalf("Unexpected construction error %v", err)
}
return kt
}

View File

@@ -1,93 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/internal/k8sdeps/transformer"
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
. "sigs.k8s.io/kustomize/api/internal/target"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
)
func TestPluginDir(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
tc.BuildExecPlugin(
"someteam.example.com", "v1", "PrintWorkDir")
base, err := os.Getwd()
if err != nil {
t.Fatalf("err %v", err)
}
dir, err := ioutil.TempDir(base, "kustomize-")
if err != nil {
t.Fatalf("err %v", err)
}
defer os.RemoveAll(dir)
fSys := filesys.MakeFsOnDisk()
err = fSys.WriteFile(filepath.Join(dir, "kustomization.yaml"), []byte(`
generators:
- config.yaml
`))
if err != nil {
t.Fatalf("err %v", err)
}
err = fSys.WriteFile(filepath.Join(dir, "config.yaml"), []byte(`
apiVersion: someteam.example.com/v1
kind: PrintWorkDir
metadata:
name: some-random-name
`))
if err != nil {
t.Fatalf("err %v", err)
}
ldr, err := fLdr.NewLoader(
fLdr.RestrictionRootOnly, dir, fSys)
if err != nil {
t.Fatalf("Err: %v", err)
}
rf := resmap.NewFactory(resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl()), nil)
c, err := konfig.EnabledPluginConfig()
if err != nil {
t.Fatal(err)
}
pl := pLdr.NewLoader(c, rf)
tg, err := NewKustTarget(
ldr, valtest_test.MakeFakeValidator(), rf, transformer.NewFactoryImpl(), pl)
if err != nil {
t.Fatalf("err %v", err)
}
m, err := tg.MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
th := kusttest_test.NewKustTestHarness(t, ".")
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: WorkDir
metadata:
name: `+dir+`
spec:
path: `+dir+`
`)
}

View File

@@ -0,0 +1,188 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
import (
"fmt"
"strings"
"testing"
"sigs.k8s.io/kustomize/api/resid"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
"sigs.k8s.io/kustomize/api/types"
)
// To simplify tests, these vars specified in alphabetical order.
var someVars = []types.Var{
{
Name: "AWARD",
ObjRef: types.Target{
APIVersion: "v7",
Gvk: resid.Gvk{Kind: "Service"},
Name: "nobelPrize"},
FieldRef: types.FieldSelector{FieldPath: "some.arbitrary.path"},
},
{
Name: "BIRD",
ObjRef: types.Target{
APIVersion: "v300",
Gvk: resid.Gvk{Kind: "Service"},
Name: "heron"},
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
},
{
Name: "FRUIT",
ObjRef: types.Target{
Gvk: resid.Gvk{Kind: "Service"},
Name: "apple"},
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
},
{
Name: "VEGETABLE",
ObjRef: types.Target{
Gvk: resid.Gvk{Kind: "Leafy"},
Name: "kale"},
FieldRef: types.FieldSelector{FieldPath: "metadata.name"},
},
}
func TestGetAllVarsSimple(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
vars:
- name: AWARD
objref:
kind: Service
name: nobelPrize
apiVersion: v7
fieldref:
fieldpath: some.arbitrary.path
- name: BIRD
objref:
kind: Service
name: heron
apiVersion: v300
`)
ra, err := makeKustTarget(
t, th.GetFSys(), "/app").AccumulateTarget()
if err != nil {
t.Fatalf("Err: %v", err)
}
vars := ra.Vars()
if len(vars) != 2 {
t.Fatalf("unexpected size %d", len(vars))
}
for i := range vars[:2] {
// By using Var.DeepEqual, we are protecting the code
// from a potential invocation of vars[i].ObjRef.GVK()
// during accumulateTarget
if !vars[i].DeepEqual(someVars[i]) {
t.Fatalf("unexpected var[%d]:\n %v\n %v", i, vars[i], someVars[i])
}
}
}
func TestGetAllVarsNested(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
vars:
- name: AWARD
objref:
kind: Service
name: nobelPrize
apiVersion: v7
fieldref:
fieldpath: some.arbitrary.path
- name: BIRD
objref:
kind: Service
name: heron
apiVersion: v300
`)
th.WriteK("/app/overlays/o1", `
vars:
- name: FRUIT
objref:
kind: Service
name: apple
resources:
- ../../base
`)
th.WriteK("/app/overlays/o2", `
vars:
- name: VEGETABLE
objref:
kind: Leafy
name: kale
resources:
- ../o1
`)
ra, err := makeKustTarget(
t, th.GetFSys(), "/app/overlays/o2").AccumulateTarget()
if err != nil {
t.Fatalf("Err: %v", err)
}
vars := ra.Vars()
if len(vars) != 4 {
for i, v := range vars {
fmt.Printf("%v: %v\n", i, v)
}
t.Fatalf("expected 4 vars, got %d", len(vars))
}
for i := range vars {
// By using Var.DeepEqual, we are protecting the code
// from a potential invocation of vars[i].ObjRef.GVK()
// during accumulateTarget
if !vars[i].DeepEqual(someVars[i]) {
t.Fatalf("unexpected var[%d]:\n %v\n %v", i, vars[i], someVars[i])
}
}
}
func TestVarCollisionsForbidden(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
vars:
- name: AWARD
objref:
kind: Service
name: nobelPrize
apiVersion: v7
fieldref:
fieldpath: some.arbitrary.path
- name: BIRD
objref:
kind: Service
name: heron
apiVersion: v300
`)
th.WriteK("/app/overlays/o1", `
vars:
- name: AWARD
objref:
kind: Service
name: academy
resources:
- ../../base
`)
th.WriteK("/app/overlays/o2", `
vars:
- name: VEGETABLE
objref:
kind: Leafy
name: kale
resources:
- ../o1
`)
_, err := makeKustTarget(
t, th.GetFSys(), "/app/overlays/o2").AccumulateTarget()
if err == nil {
t.Fatalf("expected var collision")
}
if !strings.Contains(err.Error(),
"var 'AWARD' already encountered") {
t.Fatalf("unexpected error: %v", err)
}
}

View File

@@ -139,7 +139,7 @@ func CurrentWorkingDir() string {
if len(pwd) > 0 {
return pwd
}
return "."
return filesys.SelfDir
}
func pwdEnv() string {

View File

@@ -0,0 +1,95 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"path/filepath"
"strings"
"testing"
. "sigs.k8s.io/kustomize/api/internal/target"
"sigs.k8s.io/kustomize/api/konfig"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func TestTargetMustHaveKustomizationFile(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteF("/app/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: aService
`)
th.WriteF("/app/deeper/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: anotherService
`)
err := th.RunWithErr("/app", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected an error")
}
if !IsMissingKustomizationFileError(err) {
t.Fatalf("unexpected error: %q", err)
}
}
func TestTargetMustHaveOnlyOneKustomizationFile(t *testing.T) {
th := kusttest_test.MakeHarness(t)
for _, n := range konfig.RecognizedKustomizationFileNames() {
th.WriteF(filepath.Join("/app", n), `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`)
}
err := th.RunWithErr("/app", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected an error")
}
if !strings.Contains(err.Error(), "Found multiple kustomization files under: /app") {
t.Fatalf("unexpected error: %q", err)
}
}
func TestBaseMustHaveKustomizationFile(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
resources:
- base
`)
th.WriteF("/app/base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: myService
spec:
selector:
backend: bungie
ports:
- port: 7002
`)
err := th.RunWithErr("/app", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected an error")
}
if !IsMissingKustomizationFileError(err) {
t.Fatalf("unexpected error: %q", err)
}
}
func TestResourceNotFound(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
resources:
- deployment.yaml
`)
err := th.RunWithErr("/app", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected an error")
}
if !strings.Contains(err.Error(), "'/app/deployment.yaml' doesn't exist") {
t.Fatalf("unexpected error: %q", err)
}
}

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -9,7 +9,7 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func writeMediumBase(th *kusttest_test.KustTestHarness) {
func writeMediumBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
namePrefix: baseprefix-
commonLabels:
@@ -59,12 +59,9 @@ spec:
}
func TestMediumBase(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
writeMediumBase(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -116,7 +113,7 @@ spec:
}
func TestMediumOverlay(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
writeMediumBase(th)
th.WriteK("/app/overlay", `
namePrefix: test-infra-
@@ -193,10 +190,7 @@ spec:
name: app-env
name: app-env
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment

View File

@@ -1,19 +1,19 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"strings"
"testing"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/loader"
. "sigs.k8s.io/kustomize/api/krusty"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
"sigs.k8s.io/kustomize/api/types"
)
func TestOrderPreserved(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
namePrefix: b-
resources:
@@ -65,11 +65,7 @@ kind: Namespace
metadata:
name: myNs2
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/prod", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Namespace
@@ -104,7 +100,7 @@ metadata:
}
func TestBaseInResourceList(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/prod", `
namePrefix: b-
resources:
@@ -124,10 +120,7 @@ spec:
selector:
backend: bungie
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/prod", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Service
@@ -139,7 +132,7 @@ spec:
`)
}
func writeSmallBase(th *kusttest_test.KustTestHarness) {
func writeSmallBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
namePrefix: a-
commonLabels:
@@ -177,12 +170,9 @@ spec:
}
func TestSmallBase(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -220,7 +210,7 @@ spec:
}
func TestSmallOverlay(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
th.WriteK("/app/overlay", `
namePrefix: b-
@@ -251,10 +241,7 @@ metadata:
spec:
replicas: 1000
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -298,9 +285,7 @@ spec:
}
func TestSharedPatchDisAllowed(t *testing.T) {
th := kusttest_test.NewKustTestHarnessFull(
t, "/app/overlay",
loader.RestrictionRootOnly, konfig.DisabledPluginConfig())
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
th.WriteK("/app/overlay", `
commonLabels:
@@ -318,10 +303,11 @@ metadata:
spec:
replicas: 1000
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
if err == nil {
t.Fatalf("expected error")
}
err := th.RunWithErr("/app/overlay", func() Options {
o := th.MakeDefaultOptions()
o.LoadRestrictions = types.LoadRestrictionsRootOnly
return o
}())
if !strings.Contains(
err.Error(),
"security; file '/app/shared/deployment-patch.yaml' is not in or below '/app/overlay'") {
@@ -330,9 +316,7 @@ spec:
}
func TestSharedPatchAllowed(t *testing.T) {
th := kusttest_test.NewKustTestHarnessFull(
t, "/app/overlay",
loader.RestrictionNone, konfig.DisabledPluginConfig())
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
th.WriteK("/app/overlay", `
commonLabels:
@@ -350,10 +334,11 @@ metadata:
spec:
replicas: 1000
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", func() Options {
o := th.MakeDefaultOptions()
o.LoadRestrictions = types.LoadRestrictionsNone
return o
}())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -397,7 +382,7 @@ spec:
}
func TestSmallOverlayJSONPatch(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
writeSmallBase(th)
th.WriteK("/app/overlay", `
resources:
@@ -415,10 +400,7 @@ patchesJson6902:
path: /spec/selector/backend
value: beagle
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -40,7 +40,7 @@ import (
// ├── kustomization.yaml
func TestBaseReuseNameConflict(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/component1/base", `
resources:
- ../../shared
@@ -117,10 +117,7 @@ resources:
- component2/overlay
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: PersistentVolumeClaim

View File

@@ -5,13 +5,13 @@
// Disabled on travis, because don't want to install helm on travis.
package target_test
package krusty_test
import (
"regexp"
"testing"
"sigs.k8s.io/kustomize/api/testutils/kusttest"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
// This is an example of using a helm chart as a base,
@@ -28,13 +28,10 @@ import (
// TODO: Download and inflate the chart, and check that
// in for the test.
func TestChartInflatorPlugin(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
th := kusttest_test.MakeEnhancedHarness(t).
PrepExecPlugin("someteam.example.com", "v1", "ChartInflator")
defer th.Reset()
tc.BuildExecPlugin(
"someteam.example.com", "v1", "ChartInflator")
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app")
th.WriteK("/app", `
generators:
- chartInflator.yaml
@@ -49,10 +46,7 @@ metadata:
chartName: minecraft
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
chartName := regexp.MustCompile("chart: minecraft-[0-9.]+")
th.AssertActualEqualsExpectedWithTweak(m,
func(x []byte) []byte {

View File

@@ -1,13 +1,15 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"strings"
"testing"
. "sigs.k8s.io/kustomize/api/krusty"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
"sigs.k8s.io/kustomize/api/types"
)
const httpsService = `
@@ -24,7 +26,7 @@ spec:
app: my-app
`
func writeStatefulSetBase(th *kusttest_test.KustTestHarness) {
func writeStatefulSetBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
resources:
- statefulset.yaml
@@ -53,7 +55,7 @@ spec:
`)
}
func writeHTTPSOverlay(th *kusttest_test.KustTestHarness) {
func writeHTTPSOverlay(th kusttest_test.Harness) {
th.WriteK("/app/https", `
resources:
- ../base
@@ -72,7 +74,7 @@ spec:
`)
}
func writeHTTPSTransformerRaw(th *kusttest_test.KustTestHarness) {
func writeHTTPSTransformerRaw(th kusttest_test.Harness) {
th.WriteF("/app/https/service/https-svc.yaml", httpsService)
th.WriteF("/app/https/transformer/transformer.yaml", `
apiVersion: builtin
@@ -94,7 +96,7 @@ patch: |-
`)
}
func writeHTTPSTransformerBase(th *kusttest_test.KustTestHarness) {
func writeHTTPSTransformerBase(th kusttest_test.Harness) {
th.WriteK("/app/https/service", `
resources:
- https-svc.yaml
@@ -106,7 +108,7 @@ resources:
writeHTTPSTransformerRaw(th)
}
func writeConfigFromEnvOverlay(th *kusttest_test.KustTestHarness) {
func writeConfigFromEnvOverlay(th kusttest_test.Harness) {
th.WriteK("/app/config", `
resources:
- ../base
@@ -135,7 +137,7 @@ spec:
`)
}
func writeConfigFromEnvTransformerRaw(th *kusttest_test.KustTestHarness) {
func writeConfigFromEnvTransformerRaw(th kusttest_test.Harness) {
th.WriteF("/app/config/map/generator.yaml", `
apiVersion: builtin
kind: ConfigMapGenerator
@@ -170,7 +172,7 @@ patch: |-
name: my-config
`)
}
func writeConfigFromEnvTransformerBase(th *kusttest_test.KustTestHarness) {
func writeConfigFromEnvTransformerBase(th kusttest_test.Harness) {
th.WriteK("/app/config/map", `
resources:
- generator.yaml
@@ -182,7 +184,7 @@ resources:
writeConfigFromEnvTransformerRaw(th)
}
func writeTolerationsOverlay(th *kusttest_test.KustTestHarness) {
func writeTolerationsOverlay(th kusttest_test.Harness) {
th.WriteK("/app/tolerations", `
resources:
- ../base
@@ -204,7 +206,7 @@ spec:
`)
}
func writeTolerationsTransformerRaw(th *kusttest_test.KustTestHarness) {
func writeTolerationsTransformerRaw(th kusttest_test.Harness) {
th.WriteF("/app/tolerations/transformer.yaml", `
apiVersion: builtin
kind: PatchTransformer
@@ -230,7 +232,7 @@ patch: |-
`)
}
func writeTolerationsTransformerBase(th *kusttest_test.KustTestHarness) {
func writeTolerationsTransformerBase(th kusttest_test.Harness) {
th.WriteK("/app/tolerations", `
resources:
- transformer.yaml
@@ -238,7 +240,7 @@ resources:
writeTolerationsTransformerRaw(th)
}
func writeStorageOverlay(th *kusttest_test.KustTestHarness) {
func writeStorageOverlay(th kusttest_test.Harness) {
th.WriteK("/app/storage", `
resources:
- ../base
@@ -255,7 +257,7 @@ patchesJson6902:
`)
}
func writeStorageTransformerRaw(th *kusttest_test.KustTestHarness) {
func writeStorageTransformerRaw(th kusttest_test.Harness) {
th.WriteF("/app/storage/transformer.yaml", `
apiVersion: builtin
kind: PatchTransformer
@@ -271,7 +273,7 @@ patch: |-
`)
}
func writeStorageTransformerBase(th *kusttest_test.KustTestHarness) {
func writeStorageTransformerBase(th kusttest_test.Harness) {
th.WriteK("/app/storage", `
resources:
- transformer.yaml
@@ -279,14 +281,14 @@ resources:
writeStorageTransformerRaw(th)
}
func writePatchingOverlays(th *kusttest_test.KustTestHarness) {
func writePatchingOverlays(th kusttest_test.Harness) {
writeStorageOverlay(th)
writeConfigFromEnvOverlay(th)
writeTolerationsOverlay(th)
writeHTTPSOverlay(th)
}
func writePatchingTransformersRaw(th *kusttest_test.KustTestHarness) {
func writePatchingTransformersRaw(th kusttest_test.Harness) {
writeStorageTransformerRaw(th)
writeConfigFromEnvTransformerRaw(th)
writeTolerationsTransformerRaw(th)
@@ -309,7 +311,7 @@ func writePatchingTransformersRaw(th *kusttest_test.KustTestHarness) {
// must be self-contained, i.e. the config may not have fields that
// refer to local files, since those files won't be present when
// the plugin is instantiated and used.
func writePatchingTransformerBases(th *kusttest_test.KustTestHarness) {
func writePatchingTransformerBases(th kusttest_test.Harness) {
writeStorageTransformerBase(th)
writeConfigFromEnvTransformerBase(th)
writeTolerationsTransformerBase(th)
@@ -352,7 +354,7 @@ func writePatchingTransformerBases(th *kusttest_test.KustTestHarness) {
// - prod: Combines the config, tolerations and https intermediate overlays.
func TestComplexComposition_Dev_Failure(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/dev")
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingOverlays(th)
th.WriteK("/app/dev", `
@@ -360,7 +362,7 @@ resources:
- ../storage
- ../config
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app/dev", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("Expected resource accumulation error")
}
@@ -404,7 +406,7 @@ metadata:
`
func TestComplexComposition_Dev_SuccessWithRawTransformers(t *testing.T) {
th := kusttest_test.NewKustTestHarnessNoLoadRestrictor(t, "/app/dev")
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingTransformersRaw(th)
th.WriteK("/app/dev", `
@@ -416,15 +418,16 @@ transformers:
- ../config/transformer/transformer.yaml
- ../storage/transformer.yaml
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
m := th.Run("/app/dev", func() Options {
o := th.MakeDefaultOptions()
o.LoadRestrictions = types.LoadRestrictionsNone
return o
}())
th.AssertActualEqualsExpected(m, devDesiredResult)
}
func TestComplexComposition_Dev_SuccessWithBaseTransformers(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/dev")
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingTransformerBases(th)
th.WriteK("/app/dev", `
@@ -436,15 +439,12 @@ transformers:
- ../config/transformer
- ../storage
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
m := th.Run("/app/dev", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, devDesiredResult)
}
func TestComplexComposition_Prod_Failure(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingOverlays(th)
th.WriteK("/app/prod", `
@@ -453,7 +453,7 @@ resources:
- ../tolerations
- ../https
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app/prod", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("Expected resource accumulation error")
}
@@ -513,7 +513,7 @@ metadata:
`
func TestComplexComposition_Prod_SuccessWithRawTransformers(t *testing.T) {
th := kusttest_test.NewKustTestHarnessNoLoadRestrictor(t, "/app/prod")
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingTransformersRaw(th)
th.WriteK("/app/prod", `
@@ -527,15 +527,16 @@ transformers:
- ../https/transformer/transformer.yaml
- ../tolerations/transformer.yaml
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
m := th.Run("/app/prod", func() Options {
o := th.MakeDefaultOptions()
o.LoadRestrictions = types.LoadRestrictionsNone
return o
}())
th.AssertActualEqualsExpected(m, prodDesiredResult)
}
func TestComplexComposition_Prod_SuccessWithBaseTransformers(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
th := kusttest_test.MakeHarness(t)
writeStatefulSetBase(th)
writePatchingTransformerBases(th)
th.WriteK("/app/prod", `
@@ -549,9 +550,6 @@ transformers:
- ../https/transformer
- ../tolerations
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
m := th.Run("/app/prod", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, prodDesiredResult)
}

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -12,7 +12,7 @@ import (
// Generate a Secret and a ConfigMap from the same data
// to compare the result.
func TestGeneratorBasics(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
namePrefix: blah-
configMapGenerator:
@@ -59,10 +59,8 @@ electromagnetic
strong nuclear
weak nuclear
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -111,7 +109,7 @@ type: Opaque
// TODO: These should be errors instead.
func TestGeneratorRepeatsInKustomization(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
namePrefix: blah-
configMapGenerator:
@@ -142,10 +140,7 @@ krypton
xenon
radon
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -166,7 +161,7 @@ metadata:
}
func TestGeneratorOverlays(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base1", `
namePrefix: p1-
configMapGenerator:
@@ -212,10 +207,7 @@ configMapGenerator:
- foo=bar
- baz=qux
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -240,7 +232,8 @@ metadata:
}
func TestConfigMapGeneratorMergeNamePrefix(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
configMapGenerator:
- name: cm
@@ -272,10 +265,7 @@ configMapGenerator:
literals:
- big=crunch
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -9,7 +9,7 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func writeBaseWithCrd(th *kusttest_test.KustTestHarness) {
func writeBaseWithCrd(th kusttest_test.Harness) {
th.WriteK("/app/base", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
@@ -225,12 +225,9 @@ data:
}
func TestCrdBase(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
writeBaseWithCrd(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -259,7 +256,7 @@ spec:
}
func TestCrdWithOverlay(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
writeBaseWithCrd(th)
th.WriteK("/app/overlay", `
apiVersion: kustomize.config.k8s.io/v1beta1
@@ -278,10 +275,7 @@ metadata:
spec:
action: makehoney
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
@@ -311,7 +305,7 @@ spec:
}
func TestCrdWithContainers(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/crd/containers")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/crd/containers", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
@@ -343,10 +337,7 @@ spec:
containers:
description: Containers allows injecting additional containers
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/crd/containers", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -9,7 +9,7 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func makeBaseReferencingCustomConfig(th *kusttest_test.KustTestHarness) {
func makeBaseReferencingCustomConfig(th kusttest_test.Harness) {
th.WriteK("/app/base", `
namePrefix: x-
commonLabels:
@@ -74,9 +74,9 @@ spec:
}
func TestCustomConfig(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeBaseReferencingCustomConfig(th)
th.WriteDefaultConfigs("/app/base/config/defaults.yaml")
th.WriteLegacyConfigs("/app/base/config/defaults.yaml")
th.WriteF("/app/base/config/custom.yaml", `
nameReference:
- kind: Gorilla
@@ -91,10 +91,7 @@ varReference:
- path: spec/food
kind: AnimalPark
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
kind: AnimalPark
metadata:
@@ -140,9 +137,9 @@ spec:
}
func TestCustomConfigWithDefaultOverspecification(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeBaseReferencingCustomConfig(th)
th.WriteDefaultConfigs("/app/base/config/defaults.yaml")
th.WriteLegacyConfigs("/app/base/config/defaults.yaml")
// Specifying namePrefix here conflicts with (is the same as)
// the defaults written above. This is intentional in the
// test to assure duplicate config doesn't cause problems.
@@ -162,10 +159,7 @@ varReference:
- path: spec/food
kind: AnimalPark
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
kind: AnimalPark
metadata:
@@ -211,9 +205,9 @@ spec:
}
func TestFixedBug605_BaseCustomizationAvailableInOverlay(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
makeBaseReferencingCustomConfig(th)
th.WriteDefaultConfigs("/app/base/config/defaults.yaml")
th.WriteLegacyConfigs("/app/base/config/defaults.yaml")
th.WriteF("/app/base/config/custom.yaml", `
nameReference:
- kind: Gorilla
@@ -255,12 +249,7 @@ spec:
gorillaRef:
name: ursus
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
kind: AnimalPark
metadata:

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -13,13 +13,9 @@ import (
// This is a NamePrefixer that touches Deployments
// and Services exclusively.
func TestCustomNamePrefixer(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
"builtin", "", "PrefixSuffixTransformer")
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app")
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("PrefixSuffixTransformer")
defer th.Reset()
th.WriteK("/app", `
resources:
@@ -69,10 +65,7 @@ metadata:
name: myService
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -14,17 +14,11 @@ import (
// in a base, allowing them to be reused in any number of
// kustomizations.
func TestReusableCustomTransformers(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
"builtin", "", "PrefixSuffixTransformer")
tc.BuildGoPlugin(
"builtin", "", "AnnotationsTransformer")
tc.BuildGoPlugin(
"builtin", "", "LabelTransformer")
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/staging")
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("PrefixSuffixTransformer").
PrepBuiltin("AnnotationsTransformer").
PrepBuiltin("LabelTransformer")
defer th.Reset()
// First write three custom configurations for builtin plugins.
@@ -138,10 +132,7 @@ metadata:
name: myService
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/staging", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"fmt"
@@ -10,6 +10,7 @@ import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
"sigs.k8s.io/kustomize/api/types"
)
const patchAddProbe = `
@@ -57,7 +58,7 @@ spec:
`
const patchJsonRestartPolicy = `[{"op": "add", "path": "/spec/template/spec/restartPolicy", "value": "Always"}]`
func writeDeploymentBase(th *kusttest_test.KustTestHarness) {
func writeDeploymentBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
resources:
- deployment.yaml
@@ -78,7 +79,7 @@ spec:
`)
}
func writeProbeOverlay(th *kusttest_test.KustTestHarness) {
func writeProbeOverlay(th kusttest_test.Harness) {
th.WriteK("/app/probe", `
resources:
- ../base
@@ -88,7 +89,7 @@ patchesStrategicMerge:
th.WriteF("/app/probe/dep-patch.yaml", patchAddProbe)
}
func writeDNSOverlay(th *kusttest_test.KustTestHarness) {
func writeDNSOverlay(th kusttest_test.Harness) {
th.WriteK("/app/dns", `
resources:
- ../base
@@ -98,7 +99,7 @@ patchesStrategicMerge:
th.WriteF("/app/dns/dep-patch.yaml", patchDnsPolicy)
}
func writeRestartOverlay(th *kusttest_test.KustTestHarness) {
func writeRestartOverlay(th kusttest_test.Harness) {
th.WriteK("/app/restart", `
resources:
- ../base
@@ -122,7 +123,7 @@ patchesStrategicMerge:
// base
//
func TestIssue1251_CompositeDiamond_Failure(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/composite")
th := kusttest_test.MakeHarness(t)
writeDeploymentBase(th)
writeProbeOverlay(th)
writeDNSOverlay(th)
@@ -135,7 +136,7 @@ resources:
- ../restart
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app/composite", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("Expected resource accumulation error")
}
@@ -167,7 +168,7 @@ spec:
// This test reuses some methods from TestIssue1251_CompositeDiamond,
// but overwrites the kustomization files in the overlays.
func TestIssue1251_Patches_Overlayed(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/restart")
th := kusttest_test.MakeHarness(t)
writeDeploymentBase(th)
// probe overlays base.
@@ -191,15 +192,12 @@ patchesStrategicMerge:
- dep-patch.yaml
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/restart", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expectedPatchedDeployment)
}
func TestIssue1251_Patches_Local(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/composite")
th := kusttest_test.MakeHarness(t)
writeDeploymentBase(th)
th.WriteK("/app/composite", `
@@ -214,14 +212,11 @@ patchesStrategicMerge:
th.WriteF("/app/composite/patchDnsPolicy.yaml", patchDnsPolicy)
th.WriteF("/app/composite/patchAddProbe.yaml", patchAddProbe)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/composite", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expectedPatchedDeployment)
}
func definePatchDirStructure(th *kusttest_test.KustTestHarness) {
func definePatchDirStructure(th kusttest_test.Harness) {
writeDeploymentBase(th)
th.WriteF("/app/patches/patchRestartPolicy.yaml", patchRestartPolicy)
@@ -231,7 +226,7 @@ func definePatchDirStructure(th *kusttest_test.KustTestHarness) {
// Fails due to file load restrictor.
func TestIssue1251_Patches_ProdVsDev_Failure(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
th := kusttest_test.MakeHarness(t)
definePatchDirStructure(th)
th.WriteK("/app/prod", `
@@ -242,7 +237,7 @@ patchesStrategicMerge:
- ../patches/patchDnsPolicy.yaml
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app/prod", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected error")
}
@@ -304,7 +299,7 @@ spec:
// the kustomization root), opening the user to whatever
// threat the load restrictor was meant to address.
func TestIssue1251_Patches_ProdVsDev(t *testing.T) {
th := kusttest_test.NewKustTestHarnessNoLoadRestrictor(t, "/app/prod")
th := kusttest_test.MakeHarness(t)
definePatchDirStructure(th)
th.WriteK("/app/prod", `
@@ -314,13 +309,13 @@ patchesStrategicMerge:
- ../patches/patchAddProbe.yaml
- ../patches/patchDnsPolicy.yaml
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
opts := th.MakeDefaultOptions()
opts.LoadRestrictions = types.LoadRestrictionsNone
m := th.Run("/app/prod", opts)
th.AssertActualEqualsExpected(m, prodDevMergeResult1)
th = kusttest_test.NewKustTestHarnessNoLoadRestrictor(t, "/app/dev")
th = kusttest_test.MakeHarness(t)
definePatchDirStructure(th)
th.WriteK("/app/dev", `
@@ -331,21 +326,15 @@ patchesStrategicMerge:
- ../patches/patchRestartPolicy.yaml
`)
m, err = th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m = th.Run("/app/dev", opts)
th.AssertActualEqualsExpected(m, prodDevMergeResult2)
}
func TestIssue1251_Plugins_ProdVsDev(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("PatchJson6902Transformer")
defer th.Reset()
tc.BuildGoPlugin(
"builtin", "", "PatchJson6902Transformer")
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/prod")
defineTransformerDirStructure(th)
th.WriteK("/app/prod", `
resources:
@@ -355,13 +344,9 @@ transformers:
- ../patches/addDnsPolicy
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/prod", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, prodDevMergeResult1)
th = kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/dev")
defineTransformerDirStructure(th)
th.WriteK("/app/dev", `
resources:
@@ -371,22 +356,16 @@ transformers:
- ../patches/addDnsPolicy
`)
m, err = th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m = th.Run("/app/dev", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, prodDevMergeResult2)
}
func TestIssue1251_Plugins_Local(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("PatchJson6902Transformer")
defer th.Reset()
tc.BuildGoPlugin(
"builtin", "", "PatchJson6902Transformer")
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/composite")
writeDeploymentBase(th)
writeDeploymentBase(th.Harness)
writeJsonTransformerPluginConfig(
th, "/app/composite", "addDnsPolicy", patchJsonDnsPolicy)
@@ -403,15 +382,12 @@ transformers:
- addRestartPolicyConfig.yaml
- addProbeConfig.yaml
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/composite", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expectedPatchedDeployment)
}
func writeJsonTransformerPluginConfig(
th *kusttest_test.KustTestHarness, path, name, patch string) {
th *kusttest_test.HarnessEnhanced, path, name, patch string) {
th.WriteF(filepath.Join(path, name+"Config.yaml"),
fmt.Sprintf(`
apiVersion: builtin
@@ -429,14 +405,10 @@ jsonOp: '%s'
// Remote in the sense that they are bundled in a different kustomization.
func TestIssue1251_Plugins_Bundled(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
"builtin", "", "PatchJson6902Transformer")
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/composite")
writeDeploymentBase(th)
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("PatchJson6902Transformer")
defer th.Reset()
writeDeploymentBase(th.Harness)
th.WriteK("/app/patches", `
resources:
@@ -457,15 +429,12 @@ resources:
transformers:
- ../patches
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/composite", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expectedPatchedDeployment)
}
func defineTransformerDirStructure(th *kusttest_test.KustTestHarness) {
writeDeploymentBase(th)
func defineTransformerDirStructure(th *kusttest_test.HarnessEnhanced) {
writeDeploymentBase(th.Harness)
th.WriteK("/app/patches/addDnsPolicy", `
resources:

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -30,7 +30,7 @@ import (
// \ | /
// base
//
func writeDiamondBase(th *kusttest_test.KustTestHarness) {
func writeDiamondBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
resources:
- deploy.yaml
@@ -45,7 +45,7 @@ spec:
`)
}
func writeKirk(th *kusttest_test.KustTestHarness) {
func writeKirk(th kusttest_test.Harness) {
th.WriteK("/app/kirk", `
namePrefix: kirk-
resources:
@@ -72,7 +72,7 @@ data:
`)
}
func writeSpock(th *kusttest_test.KustTestHarness) {
func writeSpock(th kusttest_test.Harness) {
th.WriteK("/app/spock", `
namePrefix: spock-
resources:
@@ -90,7 +90,7 @@ spec:
`)
}
func writeBones(th *kusttest_test.KustTestHarness) {
func writeBones(th kusttest_test.Harness) {
th.WriteK("/app/bones", `
namePrefix: bones-
resources:
@@ -108,7 +108,7 @@ spec:
`)
}
func writeTenants(th *kusttest_test.KustTestHarness) {
func writeTenants(th kusttest_test.Harness) {
th.WriteK("/app/tenants", `
namePrefix: t-
resources:
@@ -139,7 +139,7 @@ data:
}
func TestBasicDiamond(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
th := kusttest_test.MakeHarness(t)
writeDiamondBase(th)
writeKirk(th)
writeSpock(th)
@@ -177,10 +177,7 @@ data:
zone: twilight
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/prod", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Deployment

View File

@@ -0,0 +1,29 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func TestIssue596AllowDirectoriesThatAreSubstringsOfEachOther(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", "")
th.WriteK("/app/overlays/aws", `
resources:
- ../../base
`)
th.WriteK("/app/overlays/aws-nonprod", `
resources:
- ../aws
`)
th.WriteK("/app/overlays/aws-sandbox2.us-east-1", `
resources:
- ../aws-nonprod
`)
m := th.Run("/app/overlays/aws-sandbox2.us-east-1", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, "")
}

View File

@@ -0,0 +1,100 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"strings"
"testing"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func findSecret(m resmap.ResMap) *resource.Resource {
for _, r := range m.Resources() {
if r.OrgId().Kind == "Secret" {
return r
}
}
return nil
}
func TestDisableNameSuffixHash(t *testing.T) {
th := kusttest_test.MakeHarness(t)
const kustomizationContent = `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: foo-
nameSuffix: -bar
namespace: ns1
commonLabels:
app: nginx
commonAnnotations:
note: This is a test annotation
resources:
- deployment.yaml
- namespace.yaml
generatorOptions:
disableNameSuffixHash: false
configMapGenerator:
- name: literalConfigMap
literals:
- DB_USERNAME=admin
- DB_PASSWORD=somepw
secretGenerator:
- name: secret
literals:
- DB_USERNAME=admin
- DB_PASSWORD=somepw
type: Opaque
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: dply1
path: jsonpatch.json
`
th.WriteK("/whatever", kustomizationContent)
th.WriteF("/whatever/deployment.yaml", `
apiVersion: apps/v1
metadata:
name: dply1
kind: Deployment
`)
th.WriteF("/whatever/namespace.yaml", `
apiVersion: v1
kind: Namespace
metadata:
name: ns1
`)
th.WriteF("/whatever/jsonpatch.json", `[
{"op": "add", "path": "/spec/replica", "value": "3"}
]`)
m := th.Run("/whatever", th.MakeDefaultOptions())
secret := findSecret(m)
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "foo-secret-bar-9btc7bt4kb" {
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
th.WriteK("/whatever",
strings.Replace(kustomizationContent,
"disableNameSuffixHash: false",
"disableNameSuffixHash: true", -1))
m = th.Run("/whatever", th.MakeDefaultOptions())
secret = findSecret(m)
if secret == nil {
t.Errorf("Expected to find a Secret")
}
if secret.GetName() != "foo-secret-bar" { // No hash at end.
t.Errorf("unexpected secret resource name: %s", secret.GetName())
}
}

View File

@@ -1,6 +1,11 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package krusty holds a very high level API to kustomize.
// The functions here should be similar to the CLI api.
// Package krusty is intended as the entry point package
// for those seeking to add kustomize ability to other
// programs.
//
// To use, follow the example of the kustomize CLI's 'build'
// command. Also, see the high level tests in this package,
// which serve a dual purpose as examples.
package krusty

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -9,7 +9,7 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func makeCommonFileForExtendedPatchTest(th *kusttest_test.KustTestHarness) {
func makeCommonFileForExtendedPatchTest(th kusttest_test.Harness) {
th.WriteF("/app/base/deployment.yaml", `
apiVersion: apps/v1beta2
kind: Deployment
@@ -89,7 +89,7 @@ spec:
}
func TestExtendedPatchNameSelector(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -108,10 +108,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -194,7 +191,7 @@ spec:
}
func TestExtendedPatchGvkSelector(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -213,10 +210,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -299,7 +293,7 @@ spec:
}
func TestExtendedPatchLabelSelector(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -318,10 +312,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -404,7 +395,7 @@ spec:
}
func TestExtendedPatchNameGvkSelector(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -424,10 +415,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -508,7 +496,7 @@ spec:
}
func TestExtendedPatchNameLabelSelector(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -528,10 +516,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -614,7 +599,7 @@ spec:
}
func TestExtendedPatchGvkLabelSelector(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -634,10 +619,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -718,7 +700,7 @@ spec:
}
func TestExtendedPatchNameGvkLabelSelector(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -739,10 +721,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -823,7 +802,7 @@ spec:
}
func TestExtendedPatchNoMatch(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -842,10 +821,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -924,7 +900,7 @@ spec:
}
func TestExtendedPatchWithoutTarget(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -941,10 +917,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -1025,7 +998,7 @@ spec:
}
func TestExtendedPatchNoMatchMultiplePatch(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -1048,10 +1021,7 @@ metadata:
annotations:
new-key: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -1130,7 +1100,7 @@ spec:
}
func TestExtendedPatchMultiplePatchOverlapping(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeCommonFileForExtendedPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -1161,10 +1131,7 @@ metadata:
annotations:
new-key-from-patch2: new-value
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"strings"
@@ -11,7 +11,7 @@ import (
)
func TestSimpleBase(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
@@ -72,10 +72,7 @@ spec:
- name: nginx
image: nginx
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Service
@@ -151,7 +148,7 @@ spec:
`)
}
func makeBaseWithGenerators(th *kusttest_test.KustTestHarness) {
func makeBaseWithGenerators(th kusttest_test.Harness) {
th.WriteK("/app", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
@@ -217,12 +214,9 @@ spec:
}
func TestBaseWithGeneratorsAlone(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
makeBaseWithGenerators(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -311,7 +305,7 @@ type: Opaque
}
func TestMergeAndReplaceGenerators(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/overlay")
th := kusttest_test.MakeHarness(t)
makeBaseWithGenerators(th)
th.WriteF("/overlay/deployment.yaml", `
apiVersion: apps/v1beta2
@@ -355,10 +349,7 @@ secretGenerator:
literals:
- proxy=haproxy
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -469,7 +460,7 @@ metadata:
}
func TestGeneratingIntoNamespaces(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
configMapGenerator:
- name: test
@@ -492,10 +483,7 @@ secretGenerator:
- username=admin
- password=somepw
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -538,7 +526,7 @@ type: Opaque
// Valid that conflict is detected is the name are identical
// and namespace left to default
func TestConfigMapGeneratingIntoSameNamespace(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
configMapGenerator:
- name: test
@@ -549,7 +537,7 @@ configMapGenerator:
literals:
- key=value
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected error")
}
@@ -561,7 +549,7 @@ configMapGenerator:
// Valid that conflict is detected is the name are identical
// and namespace left to default
func TestSecretGeneratingIntoSameNamespace(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
secretGenerator:
- name: test
@@ -574,7 +562,7 @@ secretGenerator:
- username=admin
- password=somepw
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected error")
}

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -10,7 +10,7 @@ import (
)
func TestSecretGenerator(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
secretGenerator:
- name: bob
@@ -28,10 +28,7 @@ MOUNTAIN=everest
OCEAN=pacific
`)
th.WriteF("/app/phrase.dat", "dat phrase")
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -49,7 +46,7 @@ type: Opaque
}
func TestGeneratorOptionsWithBases(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
@@ -76,10 +73,7 @@ configMapGenerator:
literals:
- fruit=apple
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -9,7 +9,7 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func makeResourcesForPatchTest(th *kusttest_test.KustTestHarness) {
func makeResourcesForPatchTest(th kusttest_test.Harness) {
th.WriteF("/app/base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
@@ -39,7 +39,7 @@ spec:
}
func TestStrategicMergePatchInline(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeResourcesForPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -58,10 +58,7 @@ patchesStrategicMerge:
- name: nginx
image: image1
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -91,7 +88,7 @@ spec:
}
func TestJSONPatchInline(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeResourcesForPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -108,10 +105,7 @@ patchesJson6902:
path: /spec/template/spec/containers/0/image
value: image1
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -141,7 +135,7 @@ spec:
}
func TestExtendedPatchInlineJSON(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeResourcesForPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -156,10 +150,7 @@ patches:
path: /spec/template/spec/containers/0/image
value: image1
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -189,7 +180,7 @@ spec:
}
func TestExtendedPatchInlineYAML(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeResourcesForPatchTest(th)
th.WriteK("/app/base", `
resources:
@@ -211,10 +202,7 @@ patches:
- name: nginx
image: image1
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment

View File

@@ -22,7 +22,7 @@ import (
// performing an exec to a kustomize CLI subprocess.
// To use, load a filesystem with kustomization files (any
// number of overlays and bases), then make a Kustomizer
// injected with the given fileystem, then call Build.
// injected with the given fileystem, then call Run.
type Kustomizer struct {
fSys filesys.FileSystem
options *Options
@@ -59,13 +59,14 @@ func (b *Kustomizer) Run(path string) (resmap.ResMap, error) {
return nil, err
}
defer ldr.Cleanup()
kt, err := target.NewKustTarget(
kt := target.NewKustTarget(
ldr,
validator.NewKustValidator(),
rf,
pf,
pLdr.NewLoader(b.options.PluginConfig, rf),
)
err = kt.Load()
if err != nil {
return nil, err
}

View File

@@ -1,7 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// TODO: move most of the tests in the api/target package to this package.
package krusty_test
import (
@@ -11,14 +10,18 @@ import (
"sigs.k8s.io/kustomize/api/krusty"
)
func TestSomething1(t *testing.T) {
// A simple usage example to shows what happens when
// there are no files to read.
// For more substantial tests and examples,
// see other tests in this package.
func TestEmptyFileSystem(t *testing.T) {
fSys := filesys.MakeFsInMemory()
b := krusty.MakeKustomizer(fSys, krusty.MakeDefaultOptions())
_, err := b.Run("hey")
_, err := b.Run("noSuchThing")
if err == nil {
t.Fatalf("expected error")
}
if err.Error() != "got file 'hey', but 'hey' must be a directory to be a root" {
if err.Error() != "'noSuchThing' doesn't exist" {
t.Fatalf("unexpected error: %v", err)
}
}

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"strings"
@@ -10,7 +10,7 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func makeCommonFileForMultiplePatchTest(th *kusttest_test.KustTestHarness) {
func makeCommonFileForMultiplePatchTest(th kusttest_test.Harness) {
th.WriteK("/app/base", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
@@ -89,7 +89,7 @@ configMapGenerator:
}
func TestMultiplePatchesNoConflict(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay/staging")
th := kusttest_test.MakeHarness(t)
makeCommonFileForMultiplePatchTest(th)
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
apiVersion: apps/v1beta2
@@ -130,10 +130,7 @@ spec:
volumes:
- name: nginx-persistent-storage
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2
kind: Deployment
@@ -233,7 +230,7 @@ metadata:
}
func TestMultiplePatchesWithConflict(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay/staging")
th := kusttest_test.MakeHarness(t)
makeCommonFileForMultiplePatchTest(th)
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
apiVersion: apps/v1beta2
@@ -271,7 +268,7 @@ spec:
- name: ENABLE_FEATURE_FOO
value: FALSE
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app/overlay/staging", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected conflict")
}
@@ -325,15 +322,12 @@ spec:
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay/staging")
th := kusttest_test.MakeHarness(t)
makeCommonFileForMultiplePatchTest(th)
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", c.patch1)
th.WriteF("/app/overlay/staging/deployment-patch2.yaml", c.patch2)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `apiVersion: apps/v1beta2
kind: Deployment
metadata:
@@ -426,7 +420,7 @@ metadata:
}
func TestMultiplePatchesBothWithPatchDeleteDirective(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay/staging")
th := kusttest_test.MakeHarness(t)
makeCommonFileForMultiplePatchTest(th)
th.WriteF("/app/overlay/staging/deployment-patch1.yaml", `
apiVersion: apps/v1beta2
@@ -452,7 +446,7 @@ spec:
- $patch: delete
name: nginx
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app/overlay/staging", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("Expected error")
}

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -10,7 +10,7 @@ import (
)
func TestNamespacedGenerator(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
@@ -34,10 +34,7 @@ secretGenerator:
literals:
- password.txt=anotherSecret
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -76,7 +73,7 @@ type: Opaque
}
func TestNamespacedGeneratorWithOverlays(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
namespace: base
@@ -97,10 +94,7 @@ configMapGenerator:
literals:
- overlay=true
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"strings"
@@ -11,8 +11,7 @@ import (
)
func TestNamespacedSecrets(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteF("/app/secrets.yaml", `
apiVersion: v1
kind: Secret
@@ -51,16 +50,12 @@ resources:
- secrets.yaml
- role.yaml
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
// This validates Fix #1444. This should not be an error anymore -
// the secrets have the same name but are in different namespaces.
// The ClusterRole (by def) is not in a namespace,
// an in this case applies to *any* Secret resource
// named "dummy"
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -100,7 +95,7 @@ rules:
// PrefixSuffixTransformer and namereference transformers are
// able to deal with simultaneous change of namespace and name.
func TestNameAndNsTransformation(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/nameandns")
th := kusttest_test.MakeHarness(t)
th.WriteK("/nameandns", `
namePrefix: p1-
@@ -206,11 +201,7 @@ kind: PersistentVolume
metadata:
name: pv1
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/nameandns", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ConfigMap
@@ -474,11 +465,11 @@ spec:
// using the same name in different namespaces are treated as ambiguous if the namespace is
// not specified
func TestVariablesAmbiguous(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/namespaceNeedInVar/myapp")
th := kusttest_test.MakeHarness(t)
th.WriteK("/namespaceNeedInVar/myapp", namespaceNeedInVarMyApp)
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/namespaceNeedInVar/myapp", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected error")
}
@@ -531,7 +522,7 @@ vars:
// to TestVariablesAmbiguous problem. It requires to separate the variables
// and resources into multiple kustomization context/folders instead of one.
func TestVariablesAmbiguousWorkaround(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/namespaceNeedInVar/workaround")
th := kusttest_test.MakeHarness(t)
th.WriteK("/namespaceNeedInVar/dev", namespaceNeedInVarDevFolder)
th.WriteF("/namespaceNeedInVar/dev/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
th.WriteK("/namespaceNeedInVar/test", namespaceNeedInVarTestFolder)
@@ -541,10 +532,7 @@ resources:
- ../dev
- ../test
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/namespaceNeedInVar/workaround", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, namespaceNeedInVarExpectedOutput)
}
@@ -590,13 +578,10 @@ vars:
// TestVariablesDisambiguatedWithNamespace demonstrates that adding the namespace
// to the variable declarations allows to disambiguate the variables.
func TestVariablesDisambiguatedWithNamespace(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/namespaceNeedInVar/myapp")
th := kusttest_test.MakeHarness(t)
th.WriteK("/namespaceNeedInVar/myapp", namespaceNeedInVarMyAppWithNamespace)
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-dev-service.yaml", namespaceNeedInVarDevResources)
th.WriteF("/namespaceNeedInVar/myapp/elasticsearch-test-service.yaml", namespaceNeedInVarTestResources)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/namespaceNeedInVar/myapp", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, namespaceNeedInVarExpectedOutput)
}

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -10,7 +10,7 @@ import (
)
func TestNullValues(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteF("/app/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
@@ -38,10 +38,7 @@ kind: Kustomization
resources:
- deployment.yaml
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1

View File

@@ -0,0 +1,79 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package krusty_test
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/konfig"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
// The PrintPluginEnv plugin is a toy plugin that emits
// its working directory and some environment variables,
// to add regression protection to plugin loading logic.
func TestPluginEnvironment(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t).
PrepExecPlugin(
"someteam.example.com", "v1", "PrintPluginEnv")
defer th.Reset()
confirmBehavior(
kusttest_test.MakeHarnessWithFs(t, filesys.MakeFsInMemory()),
filesys.Separator)
dir := makeTmpDir(t)
defer os.RemoveAll(dir)
confirmBehavior(
kusttest_test.MakeHarnessWithFs(t, filesys.MakeFsOnDisk()),
dir)
}
func confirmBehavior(th kusttest_test.Harness, dir string) {
th.WriteK(dir, `
generators:
- config.yaml
`)
th.WriteF(filepath.Join(dir, "config.yaml"), `
apiVersion: someteam.example.com/v1
kind: PrintPluginEnv
metadata:
name: irrelevantHere
`)
m := th.Run(dir, th.MakeOptionsPluginsEnabled())
pHome, ok := os.LookupEnv(konfig.KustomizePluginHomeEnv)
if !ok {
th.GetT().Fatalf(
"expected env var '%s' to be defined",
konfig.KustomizePluginHomeEnv)
}
th.AssertActualEqualsExpected(m, `
apiVersion: v1
env:
kustomize_plugin_config_root: `+dir+`
kustomize_plugin_home: `+pHome+`
pwd: `+dir+`
kind: GeneratedEnv
metadata:
name: hello
`)
}
func makeTmpDir(t *testing.T) string {
base, err := os.Getwd()
if err != nil {
t.Fatalf("err %v", err)
}
dir, err := ioutil.TempDir(base, "kustomize-tmp-test-")
if err != nil {
t.Fatalf("err %v", err)
}
return dir
}

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -10,7 +10,7 @@ import (
)
func TestPruneConfigMap(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
resources:
- deployment.yaml
@@ -88,10 +88,7 @@ data:
username: jingfang
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
//nolint
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1beta2

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"strings"
@@ -10,7 +10,7 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func writeBase(th *kusttest_test.KustTestHarness) {
func writeBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
resources:
- serviceaccount.yaml
@@ -64,7 +64,7 @@ rules:
`)
}
func writeMidOverlays(th *kusttest_test.KustTestHarness) {
func writeMidOverlays(th kusttest_test.Harness) {
// Mid-level overlays
th.WriteK("/app/overlays/a", `
resources:
@@ -80,7 +80,7 @@ nameSuffix: -suffixB
`)
}
func writeTopOverlay(th *kusttest_test.KustTestHarness) {
func writeTopOverlay(th kusttest_test.Harness) {
// Top overlay, combining the mid-level overlays
th.WriteK("/app/combined", `
resources:
@@ -90,12 +90,9 @@ resources:
}
func TestBase(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
writeBase(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
@@ -143,13 +140,10 @@ rules:
}
func TestMidLevelA(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlays/a")
th := kusttest_test.MakeHarness(t)
writeBase(th)
writeMidOverlays(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
m := th.Run("/app/overlays/a", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
@@ -197,13 +191,10 @@ rules:
}
func TestMidLevelB(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlays/b")
th := kusttest_test.MakeHarness(t)
writeBase(th)
writeMidOverlays(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
m := th.Run("/app/overlays/b", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
@@ -251,14 +242,11 @@ rules:
}
func TestMultibasesNoConflict(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/combined")
th := kusttest_test.MakeHarness(t)
writeBase(th)
writeMidOverlays(th)
writeTopOverlay(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Unexpected err: %v", err)
}
m := th.Run("/app/combined", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
@@ -349,7 +337,7 @@ rules:
}
func TestMultibasesWithConflict(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/combined")
th := kusttest_test.MakeHarness(t)
writeBase(th)
writeMidOverlays(th)
writeTopOverlay(th)
@@ -370,7 +358,7 @@ metadata:
name: serviceaccount
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app/combined", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("expected error")
}

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -10,7 +10,7 @@ import (
"sigs.k8s.io/kustomize/api/types"
)
func writeDeployment(th *kusttest_test.KustTestHarness, path string) {
func writeDeployment(th *kusttest_test.HarnessEnhanced, path string) {
th.WriteF(path, `
apiVersion: apps/v1
kind: Deployment
@@ -28,8 +28,7 @@ spec:
`)
}
func writeStringPrefixer(
th *kusttest_test.KustTestHarness, path, name string) {
func writeStringPrefixer(th *kusttest_test.HarnessEnhanced, path, name string) {
th.WriteF(path, `
apiVersion: someteam.example.com/v1
kind: StringPrefixer
@@ -38,8 +37,7 @@ metadata:
`)
}
func writeDatePrefixer(
th *kusttest_test.KustTestHarness, path, name string) {
func writeDatePrefixer(th *kusttest_test.HarnessEnhanced, path, name string) {
th.WriteF(path, `
apiVersion: someteam.example.com/v1
kind: DatePrefixer
@@ -49,16 +47,11 @@ metadata:
}
func TestOrderedTransformers(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
th := kusttest_test.MakeEnhancedHarness(t).
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer").
BuildGoPlugin("someteam.example.com", "v1", "DatePrefixer")
defer th.Reset()
tc.BuildGoPlugin(
"someteam.example.com", "v1", "StringPrefixer")
tc.BuildGoPlugin(
"someteam.example.com", "v1", "DatePrefixer")
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app")
th.WriteK("/app", `
resources:
- deployment.yaml
@@ -73,10 +66,7 @@ transformers:
writeStringPrefixer(th, "/app/peachPrefixer.yaml", "peach")
writeDatePrefixer(th, "/app/date1Prefixer.yaml", "date1")
writeDatePrefixer(th, "/app/date2Prefixer.yaml", "date2")
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -95,20 +85,16 @@ spec:
}
func TestPluginsNotEnabled(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
th := kusttest_test.MakeEnhancedHarness(t).
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer")
defer th.Reset()
tc.BuildGoPlugin(
"someteam.example.com", "v1", "StringPrefixer")
th := kusttest_test.NewKustTestHarness(t, "/app")
th.WriteK("/app", `
transformers:
- stringPrefixer.yaml
`)
writeStringPrefixer(th, "/app/stringPrefixer.yaml", "apple")
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app", th.MakeOptionsPluginsDisabled())
if err == nil {
t.Fatalf("expected error")
}
@@ -118,13 +104,10 @@ transformers:
}
func TestSedTransformer(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
th := kusttest_test.MakeEnhancedHarness(t).
PrepExecPlugin("someteam.example.com", "v1", "SedTransformer")
defer th.Reset()
tc.BuildExecPlugin(
"someteam.example.com", "v1", "SedTransformer")
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app")
th.WriteK("/app", `
resources:
- configmap.yaml
@@ -161,10 +144,7 @@ data:
foo: $FOO
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
data:
@@ -186,16 +166,10 @@ metadata:
}
func TestTransformedTransformers(t *testing.T) {
tc := kusttest_test.NewPluginTestEnv(t).Set()
defer tc.Reset()
tc.BuildGoPlugin(
"someteam.example.com", "v1", "StringPrefixer")
tc.BuildGoPlugin(
"someteam.example.com", "v1", "DatePrefixer")
th := kusttest_test.NewKustTestHarnessAllowPlugins(t, "/app/overlay")
th := kusttest_test.MakeEnhancedHarness(t).
BuildGoPlugin("someteam.example.com", "v1", "StringPrefixer").
BuildGoPlugin("someteam.example.com", "v1", "DatePrefixer")
defer th.Reset()
th.WriteK("/app/base", `
resources:
@@ -214,10 +188,7 @@ transformers:
`)
writeDeployment(th, "/app/overlay/deployment.yaml")
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -9,7 +9,7 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func makeStatefulSetKustomization(th *kusttest_test.KustTestHarness) {
func makeStatefulSetKustomization(th kusttest_test.Harness) {
th.WriteK("/app", `
commonLabels:
notIn: arrays
@@ -92,12 +92,9 @@ spec:
}
func TestTransformersNoCreateArrays(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
makeStatefulSetKustomization(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: StatefulSet

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"testing"
@@ -9,7 +9,7 @@ import (
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func makeTransfomersImageBase(th *kusttest_test.KustTestHarness) {
func makeTransfomersImageBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
resources:
- deploy1.yaml
@@ -94,8 +94,7 @@ spec3:
}
func TestIssue1281_JsonPatchAndImageTag(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
resources:
- deployment.yaml
@@ -147,10 +146,7 @@ spec:
"value": { "image": "costello" } } ]
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -178,12 +174,9 @@ spec:
}
func TestTransfomersImageDefaultConfig(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeTransfomersImageBase(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
group: apps
@@ -242,7 +235,7 @@ spec3:
`)
}
func makeTransfomersImageCustomBase(th *kusttest_test.KustTestHarness) {
func makeTransfomersImageCustomBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
resources:
- custom.yaml
@@ -313,13 +306,11 @@ images:
path: spec3/template/spec/myInitContainers/image
`)
}
func TestTransfomersImageCustomConfig(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeTransfomersImageCustomBase(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
kind: customKind
metadata:
@@ -357,7 +348,7 @@ spec3:
`)
}
func makeTransfomersImageKnativeBase(th *kusttest_test.KustTestHarness) {
func makeTransfomersImageKnativeBase(th kusttest_test.Harness) {
th.WriteK("/app/base", `
resources:
- knative.yaml
@@ -389,12 +380,9 @@ images:
}
func TestTransfomersImageKnativeConfig(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
makeTransfomersImageKnativeBase(th)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: serving.knative.dev/v1alpha1
kind: Service

View File

@@ -1,7 +1,7 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package target_test
package krusty_test
import (
"strings"
@@ -11,7 +11,7 @@ import (
)
func TestBasicVariableRef(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
namePrefix: base-
resources:
@@ -42,10 +42,7 @@ spec:
- name: FOO
value: "$(POD_NAME)"
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Pod
@@ -65,7 +62,7 @@ spec:
}
func TestBasicVarCollision(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base1", `
namePrefix: base1-
resources:
@@ -131,7 +128,7 @@ resources:
- ../base1
- ../base2
`)
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app/overlay", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("should have an error")
}
@@ -141,7 +138,7 @@ resources:
}
func TestVarPropagatesUp(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base1", `
namePrefix: base1-
resources:
@@ -227,10 +224,7 @@ spec:
- name: P2
value: "$(POD_NAME2)"
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Pod
@@ -287,7 +281,7 @@ spec:
// are global. So if a base with a variable is included
// twice, it's a collision, so it's denied.
func TestBug506(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/top")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
namePrefix: base-
resources:
@@ -357,7 +351,7 @@ resources:
name: myServer
`
*/
_, err := th.MakeKustTarget().MakeCustomizedResMap()
err := th.RunWithErr("/app/top", th.MakeDefaultOptions())
if err == nil {
t.Fatalf("should have an error")
}
@@ -367,7 +361,7 @@ resources:
}
func TestVarRefBig(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay/staging")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
namePrefix: base-
resources:
@@ -684,10 +678,7 @@ namePrefix: dev-
resources:
- ../../base
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay/staging", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: ServiceAccount
@@ -936,7 +927,7 @@ metadata:
}
func TestVariableRefIngress(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/overlay")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
resources:
- service.yaml
@@ -1015,10 +1006,7 @@ nameprefix: kustomized-
resources:
- ../base
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/overlay", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Service
@@ -1078,7 +1066,7 @@ spec:
}
func TestVariableRefMountPath(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
resources:
- deployment.yaml
@@ -1120,10 +1108,7 @@ vars:
name: my-namespace
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -1153,7 +1138,7 @@ metadata:
}
func TestVariableRefMaps(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
resources:
- deployment.yaml
@@ -1186,10 +1171,7 @@ vars:
name: my-namespace
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
@@ -1212,7 +1194,7 @@ metadata:
}
func TestVaribaleRefDifferentPrefix(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/base")
th := kusttest_test.MakeHarness(t)
th.WriteK("/app/base", `
namePrefix: base-
resources:
@@ -1299,11 +1281,7 @@ spec:
clusterIP: None
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
m := th.Run("/app/base", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: StatefulSet

View File

@@ -93,20 +93,18 @@ type fileLoader struct {
cleaner func() error
}
const CWD = "."
// NewFileLoaderAtCwd returns a loader that loads from ".".
// NewFileLoaderAtCwd returns a loader that loads from PWD.
// A convenience for kustomize edit commands.
func NewFileLoaderAtCwd(fSys filesys.FileSystem) *fileLoader {
return newLoaderOrDie(
RestrictionRootOnly, fSys, CWD)
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, string(filepath.Separator))
RestrictionRootOnly, fSys, filesys.Separator)
}
// Root returns the absolute path that is prepended to any
@@ -150,8 +148,7 @@ func demandDirectoryRoot(
}
d, f, err := fSys.CleanedAbs(path)
if err != nil {
return "", fmt.Errorf(
"absolute path error in '%s' : %v", path, err)
return "", err
}
if f != "" {
return "", fmt.Errorf(

View File

@@ -45,7 +45,7 @@ var testCases = []testData{
func MakeFakeFs(td []testData) filesys.FileSystem {
fSys := filesys.MakeFsInMemory()
for _, x := range td {
fSys.WriteFile("/"+x.path, []byte(x.expectedContent))
fSys.WriteFile(x.path, []byte(x.expectedContent))
}
return fSys
}
@@ -131,7 +131,7 @@ func TestLoaderBadRelative(t *testing.T) {
}
// It's not okay to stay at the same place.
l2, err = l1.New(".")
l2, err = l1.New(filesys.SelfDir)
if err == nil {
t.Fatalf("expected err, but got root %s", l2.Root())
}

View File

@@ -19,7 +19,7 @@ func RestrictionRootOnly(
return "", err
}
if f == "" {
return "", fmt.Errorf("'%s' must be a file", path)
return "", fmt.Errorf("'%s' must resolve to a file", path)
}
if !d.HasPrefix(root) {
return "", fmt.Errorf(

View File

@@ -4,6 +4,7 @@
package loader
import (
"path/filepath"
"strings"
"testing"
@@ -25,9 +26,11 @@ func TestRestrictionNone(t *testing.T) {
func TestRestrictionRootOnly(t *testing.T) {
fSys := filesys.MakeFsInMemory()
root := filesys.ConfirmedDir("/tmp/foo")
root := filesys.ConfirmedDir(
filesys.Separator + filepath.Join("tmp", "foo"))
path := filepath.Join(string(root), "whatever", "beans")
path := "/tmp/foo/whatever/beans"
fSys.Create(path)
p, err := RestrictionRootOnly(fSys, root, path)
if err != nil {
t.Fatal(err)
@@ -37,18 +40,21 @@ func TestRestrictionRootOnly(t *testing.T) {
}
// Legal.
path = "/tmp/foo/whatever/../../foo/whatever"
path = filepath.Join(
string(root), "whatever", "..", "..", "foo", "whatever", "beans")
p, err = RestrictionRootOnly(fSys, root, path)
if err != nil {
t.Fatal(err)
}
path = "/tmp/foo/whatever"
path = filepath.Join(
string(root), "whatever", "beans")
if p != path {
t.Fatalf("expected '%s', got '%s'", path, p)
}
// Illegal.
path = "/tmp/illegal"
// Illegal; file exists but is out of bounds.
path = filepath.Join(filesys.Separator+"tmp", "illegal")
fSys.Create(path)
_, err = RestrictionRootOnly(fSys, root, path)
if err == nil {
t.Fatal("should have an error")

View File

@@ -8,13 +8,11 @@ import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/api/resid"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/loadertest"
"sigs.k8s.io/kustomize/api/kv"
"sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resid"
. "sigs.k8s.io/kustomize/api/resmap"
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
@@ -22,7 +20,6 @@ import (
)
func TestFromFile(t *testing.T) {
resourceStr := `apiVersion: apps/v1
kind: Deployment
metadata:
@@ -42,10 +39,6 @@ metadata:
namespace: test
---
`
l := loadertest.NewFakeLoader("/whatever/project")
if ferr := l.AddFile("/whatever/project/deployment.yaml", []byte(resourceStr)); ferr != nil {
t.Fatalf("Error adding fake file: %v\n", ferr)
}
expected := resmaptest_test.NewRmBuilder(t, rf).
Add(map[string]interface{}{
"apiVersion": "apps/v1",
@@ -67,7 +60,22 @@ metadata:
"namespace": "test",
}}).ResMap()
m, _ := rmF.FromFile(l, "deployment.yaml")
fSys := filesys.MakeFsInMemory()
err := fSys.WriteFile("deployment.yaml", []byte(resourceStr))
if err != nil {
t.Fatal(err)
}
ldr, err := loader.NewLoader(
loader.RestrictionRootOnly, filesys.Separator, fSys)
if err != nil {
t.Fatal(err)
}
m, err := rmF.FromFile(ldr, "deployment.yaml")
if err != nil {
t.Fatal(err)
}
if m.Size() != 3 {
t.Fatalf("result should contain 3, but got %d", m.Size())
}
@@ -120,8 +128,13 @@ func TestNewFromConfigMaps(t *testing.T) {
expected ResMap
}
l := loadertest.NewFakeLoader("/whatever/project")
kvLdr := kv.NewLoader(l, valtest_test.MakeFakeValidator())
fSys := filesys.MakeFsInMemory()
ldr, err := loader.NewLoader(
loader.RestrictionRootOnly, filesys.Separator, fSys)
if err != nil {
t.Fatal(err)
}
kvLdr := kv.NewLoader(ldr, valtest_test.MakeFakeValidator())
testCases := []testCase{
{
description: "construct config map from env",
@@ -135,7 +148,7 @@ func TestNewFromConfigMaps(t *testing.T) {
},
},
},
filepath: "/whatever/project/app.env",
filepath: "app.env",
content: "DB_USERNAME=admin\nDB_PASSWORD=somepw",
expected: resmaptest_test.NewRmBuilder(t, rf).Add(
map[string]interface{}{
@@ -161,7 +174,7 @@ func TestNewFromConfigMaps(t *testing.T) {
},
},
},
filepath: "/whatever/project/app-init.ini",
filepath: "app-init.ini",
content: "FOO=bar\nBAR=baz\n",
expected: resmaptest_test.NewRmBuilder(t, rf).Add(
map[string]interface{}{
@@ -209,8 +222,10 @@ BAR=baz
// files/literal/env etc.
}
for _, tc := range testCases {
if fErr := l.AddFile(tc.filepath, []byte(tc.content)); fErr != nil {
t.Fatalf("Error adding fake file: %v\n", fErr)
if tc.filepath != "" {
if fErr := fSys.WriteFile(tc.filepath, []byte(tc.content)); fErr != nil {
t.Fatalf("error adding file '%s': %v\n", tc.filepath, fErr)
}
}
r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, nil, tc.input)
if err != nil {
@@ -238,7 +253,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
},
}
fSys := filesys.MakeFsInMemory()
fSys.Mkdir(".")
fSys.Mkdir(filesys.SelfDir)
actual, err := rmF.NewResMapFromSecretArgs(
kv.NewLoader(

View File

@@ -1,18 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package resource_test
@@ -20,13 +7,13 @@ import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/api/internal/loadertest"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/loader"
. "sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
)
func TestSliceFromPatches(t *testing.T) {
patchGood1 := types.PatchStrategicMerge("patch1.yaml")
patch1 := `
apiVersion: apps/v1
@@ -131,14 +118,21 @@ kind: List
},
"spec": testDeploymentSpec,
})
l := loadertest.NewFakeLoader("/")
l.AddFile("/"+string(patchGood1), []byte(patch1))
l.AddFile("/"+string(patchGood2), []byte(patch2))
l.AddFile("/"+string(patchBad), []byte(patch3))
l.AddFile("/"+string(patchList), []byte(patch4))
l.AddFile("/"+string(patchList2), []byte(patch5))
l.AddFile("/"+string(patchList3), []byte(patch6))
l.AddFile("/"+string(patchList4), []byte(patch7))
fSys := filesys.MakeFsInMemory()
fSys.WriteFile(string(patchGood1), []byte(patch1))
fSys.WriteFile(string(patchGood2), []byte(patch2))
fSys.WriteFile(string(patchBad), []byte(patch3))
fSys.WriteFile(string(patchList), []byte(patch4))
fSys.WriteFile(string(patchList2), []byte(patch5))
fSys.WriteFile(string(patchList3), []byte(patch6))
fSys.WriteFile(string(patchList4), []byte(patch7))
ldr, err := loader.NewLoader(
loader.RestrictionRootOnly, filesys.Separator, fSys)
if err != nil {
t.Fatal(err)
}
tests := []struct {
name string
@@ -190,7 +184,7 @@ kind: List
},
}
for _, test := range tests {
rs, err := factory.SliceFromPatches(l, test.input)
rs, err := factory.SliceFromPatches(ldr, test.input)
if test.expectedErr && err == nil {
t.Fatalf("%v: should return error", test.name)
}

View File

@@ -0,0 +1,126 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kusttest_test
import (
"path/filepath"
"strings"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/konfig/builtinpluginconsts"
"sigs.k8s.io/kustomize/api/krusty"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
)
// Harness manages a kustomize environment for tests.
type Harness struct {
t *testing.T
fSys filesys.FileSystem
}
func MakeHarness(t *testing.T) Harness {
return MakeHarnessWithFs(t, filesys.MakeFsInMemory())
}
func MakeHarnessWithFs(
t *testing.T, fSys filesys.FileSystem) Harness {
return Harness{
t: t,
fSys: fSys,
}
}
func (th Harness) GetT() *testing.T {
return th.t
}
func (th Harness) GetFSys() filesys.FileSystem {
return th.fSys
}
func (th Harness) WriteK(path string, content string) {
th.fSys.WriteFile(
filepath.Join(
path,
konfig.DefaultKustomizationFileName()), []byte(`
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`+content))
}
func (th Harness) WriteF(path string, content string) {
th.fSys.WriteFile(path, []byte(content))
}
func (th Harness) MakeDefaultOptions() krusty.Options {
return th.MakeOptionsPluginsDisabled()
}
// This has no impact on Builtin plugins, as they are always enabled.
func (th Harness) MakeOptionsPluginsDisabled() krusty.Options {
return krusty.Options{
LoadRestrictions: types.LoadRestrictionsRootOnly,
PluginConfig: konfig.DisabledPluginConfig(),
}
}
// Enables use of non-builtin plugins.
func (th Harness) MakeOptionsPluginsEnabled() krusty.Options {
c, err := konfig.EnabledPluginConfig()
if err != nil {
if strings.Contains(err.Error(), "unable to find plugin root") {
th.t.Log(
"Tests that want to run with plugins enabled must be " +
"bookended by calls to MakeEnhancedHarness(), Reset().")
}
th.t.Fatal(err)
}
return krusty.Options{
LoadRestrictions: types.LoadRestrictionsRootOnly,
PluginConfig: c,
}
}
// Run, failing on error.
func (th Harness) Run(path string, o krusty.Options) resmap.ResMap {
m, err := krusty.MakeKustomizer(th.fSys, &o).Run(path)
if err != nil {
th.t.Fatal(err)
}
return m
}
// Run, failing if there is no error.
func (th Harness) RunWithErr(path string, o krusty.Options) error {
_, err := krusty.MakeKustomizer(th.fSys, &o).Run(path)
if err == nil {
th.t.Fatalf("expected error")
}
return err
}
func (th Harness) WriteLegacyConfigs(fName string) {
m := builtinpluginconsts.GetDefaultFieldSpecsAsMap()
var content []byte
for _, tCfg := range m {
content = append(content, []byte(tCfg)...)
}
err := th.fSys.WriteFile(fName, content)
if err != nil {
th.t.Fatalf("unable to add file %s", fName)
}
}
func (th Harness) AssertActualEqualsExpected(
m resmap.ResMap, expected string) {
th.AssertActualEqualsExpectedWithTweak(m, nil, expected)
}
func (th Harness) AssertActualEqualsExpectedWithTweak(
m resmap.ResMap, tweaker func([]byte) []byte, expected string) {
assertActualEqualsExpectedWithTweak(th, m, tweaker, expected)
}

View File

@@ -0,0 +1,140 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kusttest_test
import (
"testing"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/k8sdeps/transformer"
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
)
// HarnessEnhanced manages a full plugin environment for tests.
type HarnessEnhanced struct {
Harness
pte *pluginTestEnv
rf *resmap.Factory
ldr ifc.Loader
pl *pLdr.Loader
}
func MakeEnhancedHarness(t *testing.T) *HarnessEnhanced {
pte := newPluginTestEnv(t).set()
pc, err := konfig.EnabledPluginConfig()
if err != nil {
t.Fatal(err)
}
fSys := filesys.MakeFsInMemory()
rf := resmap.NewFactory(
resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()),
transformer.NewFactoryImpl())
result := &HarnessEnhanced{
Harness: Harness{t: t, fSys: fSys},
pte: pte,
rf: rf,
pl: pLdr.NewLoader(pc, rf)}
result.ResetLoaderRoot(filesys.Separator)
return result
}
func (th *HarnessEnhanced) Reset() {
th.pte.reset()
}
func (th *HarnessEnhanced) BuildGoPlugin(g, v, k string) *HarnessEnhanced {
th.pte.buildGoPlugin(g, v, k)
return th
}
func (th *HarnessEnhanced) PrepExecPlugin(g, v, k string) *HarnessEnhanced {
th.pte.prepExecPlugin(g, v, k)
return th
}
func (th *HarnessEnhanced) PrepBuiltin(k string) *HarnessEnhanced {
th.pte.buildGoPlugin(konfig.BuiltinPluginPackage, "", k)
return th
}
func (th *HarnessEnhanced) ResetLoaderRoot(root string) {
if err := th.fSys.Mkdir(root); err != nil {
th.t.Fatal(err)
}
ldr, err := fLdr.NewLoader(
fLdr.RestrictionRootOnly, root, th.fSys)
if err != nil {
th.t.Fatalf("Unable to make loader: %v", err)
}
th.ldr = ldr
}
func (th *HarnessEnhanced) LoadAndRunGenerator(
config string) resmap.ResMap {
res, err := th.rf.RF().FromBytes([]byte(config))
if err != nil {
th.t.Fatalf("Err: %v", err)
}
g, err := th.pl.LoadGenerator(
th.ldr, valtest_test.MakeFakeValidator(), res)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
rm, err := g.Generate()
if err != nil {
th.t.Fatalf("Err: %v", err)
}
return rm
}
func (th *HarnessEnhanced) LoadAndRunTransformer(
config, input string) resmap.ResMap {
resMap, err := th.RunTransformer(config, input)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
return resMap
}
func (th *HarnessEnhanced) ErrorFromLoadAndRunTransformer(
config, input string) error {
_, err := th.RunTransformer(config, input)
return err
}
func (th *HarnessEnhanced) RunTransformer(
config, input string) (resmap.ResMap, error) {
resMap, err := th.rf.NewResMapFromBytes([]byte(input))
if err != nil {
th.t.Fatalf("Err: %v", err)
}
return th.RunTransformerFromResMap(config, resMap)
}
func (th *HarnessEnhanced) RunTransformerFromResMap(
config string, resMap resmap.ResMap) (resmap.ResMap, error) {
transConfig, err := th.rf.RF().FromBytes([]byte(config))
if err != nil {
th.t.Fatalf("Err: %v", err)
}
g, err := th.pl.LoadTransformer(
th.ldr, valtest_test.MakeFakeValidator(), transConfig)
if err != nil {
return nil, err
}
err = g.Transform(resMap)
return resMap, err
}

View File

@@ -0,0 +1,104 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kusttest_test
import (
"fmt"
"strings"
"testing"
"sigs.k8s.io/kustomize/api/resmap"
)
type hasGetT interface {
GetT() *testing.T
}
func assertActualEqualsExpectedWithTweak(
ht hasGetT,
m resmap.ResMap,
tweaker func([]byte) []byte, expected string) {
if m == nil {
ht.GetT().Fatalf("Map should not be nil.")
}
// Ignore leading linefeed in expected value
// to ease readability of tests.
if len(expected) > 0 && expected[0] == 10 {
expected = expected[1:]
}
actual, err := m.AsYaml()
if err != nil {
ht.GetT().Fatalf("Unexpected err: %v", err)
}
if tweaker != nil {
actual = tweaker(actual)
}
if string(actual) != expected {
reportDiffAndFail(ht.GetT(), actual, expected)
}
}
// Pretty printing of file differences.
func reportDiffAndFail(
t *testing.T, actual []byte, expected string) {
sE, maxLen := convertToArray(expected)
sA, _ := convertToArray(string(actual))
fmt.Println("===== ACTUAL BEGIN ========================================")
fmt.Print(string(actual))
fmt.Println("===== ACTUAL END ==========================================")
format := fmt.Sprintf("%%s %%-%ds %%s\n", maxLen+4)
limit := 0
if len(sE) < len(sA) {
limit = len(sE)
} else {
limit = len(sA)
}
fmt.Printf(format, " ", "EXPECTED", "ACTUAL")
fmt.Printf(format, " ", "--------", "------")
for i := 0; i < limit; i++ {
fmt.Printf(format, hint(sE[i], sA[i]), sE[i], sA[i])
}
if len(sE) < len(sA) {
for i := len(sE); i < len(sA); i++ {
fmt.Printf(format, "X", "", sA[i])
}
} else {
for i := len(sA); i < len(sE); i++ {
fmt.Printf(format, "X", sE[i], "")
}
}
t.Fatalf("Expected not equal to actual")
}
func hint(a, b string) string {
if a == b {
return " "
}
return "X"
}
func convertToArray(x string) ([]string, int) {
a := strings.Split(strings.TrimSuffix(x, "\n"), "\n")
maxLen := 0
for i, v := range a {
z := tabToSpace(v)
if len(z) > maxLen {
maxLen = len(z)
}
a[i] = z
}
return a, maxLen
}
func tabToSpace(input string) string {
var result []string
for _, i := range input {
if i == 9 {
result = append(result, " ")
} else {
result = append(result, string(i))
}
}
return strings.Join(result, "")
}

View File

@@ -1,270 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kusttest_test
import (
"fmt"
"path/filepath"
"strings"
"testing"
"sigs.k8s.io/kustomize/api/internal/k8sdeps/transformer"
"sigs.k8s.io/kustomize/api/internal/loadertest"
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
"sigs.k8s.io/kustomize/api/internal/target"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/konfig/builtinpluginconsts"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
"sigs.k8s.io/kustomize/api/types"
)
// KustTestHarness is an environment for running a kustomize build,
// aka a run of MakeCustomizedResMap. It holds a file loader
// presumably primed with an in-memory file system, a plugin
// loader, factories to make what it needs, etc.
type KustTestHarness struct {
t *testing.T
rf *resmap.Factory
ldr loadertest.FakeLoader
pl *pLdr.Loader
}
func NewKustTestHarness(t *testing.T, path string) *KustTestHarness {
return NewKustTestHarnessFull(
t, path, fLdr.RestrictionRootOnly, konfig.DisabledPluginConfig())
}
func NewKustTestHarnessAllowPlugins(t *testing.T, path string) *KustTestHarness {
c, err := konfig.EnabledPluginConfig()
if err != nil {
t.Fatal(err)
}
return NewKustTestHarnessFull(t, path, fLdr.RestrictionRootOnly, c)
}
func NewKustTestHarnessNoLoadRestrictor(t *testing.T, path string) *KustTestHarness {
return NewKustTestHarnessFull(
t, path, fLdr.RestrictionNone, konfig.DisabledPluginConfig())
}
func NewKustTestHarnessFull(
t *testing.T, path string,
lr fLdr.LoadRestrictorFunc, pc *types.PluginConfig) *KustTestHarness {
rf := resmap.NewFactory(resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl()), transformer.NewFactoryImpl())
return &KustTestHarness{
t: t,
rf: rf,
ldr: loadertest.NewFakeLoaderWithRestrictor(lr, path),
pl: pLdr.NewLoader(pc, rf)}
}
func (th *KustTestHarness) MakeKustTarget() *target.KustTarget {
kt, err := th.MakeKustTargetOrErr()
if err != nil {
th.t.Fatalf("Unexpected construction error %v", err)
}
return kt
}
func (th *KustTestHarness) MakeKustTargetOrErr() (*target.KustTarget, error) {
return target.NewKustTarget(
th.ldr, valtest_test.MakeFakeValidator(), th.rf,
transformer.NewFactoryImpl(), th.pl)
}
func (th *KustTestHarness) WriteF(dir string, content string) {
err := th.ldr.AddFile(dir, []byte(content))
if err != nil {
th.t.Fatalf("failed write to %s; %v", dir, err)
}
}
func (th *KustTestHarness) WriteK(dir string, content string) {
th.WriteF(
filepath.Join(
dir,
konfig.DefaultKustomizationFileName()), `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`+content)
}
func (th *KustTestHarness) RF() *resource.Factory {
return th.rf.RF()
}
func (th *KustTestHarness) FromMap(m map[string]interface{}) *resource.Resource {
return th.rf.RF().FromMap(m)
}
func (th *KustTestHarness) FromMapAndOption(
m map[string]interface{},
args *types.GeneratorArgs,
option *types.GeneratorOptions) *resource.Resource {
return th.rf.RF().FromMapAndOption(m, args, option)
}
func (th *KustTestHarness) WriteDefaultConfigs(fName string) {
m := builtinpluginconsts.GetDefaultFieldSpecsAsMap()
var content []byte
for _, tCfg := range m {
content = append(content, []byte(tCfg)...)
}
err := th.ldr.AddFile(fName, content)
if err != nil {
th.t.Fatalf("unable to add file %s", fName)
}
}
func (th *KustTestHarness) LoadAndRunGenerator(
config string) resmap.ResMap {
res, err := th.rf.RF().FromBytes([]byte(config))
if err != nil {
th.t.Fatalf("Err: %v", err)
}
g, err := th.pl.LoadGenerator(
th.ldr, valtest_test.MakeFakeValidator(), res)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
rm, err := g.Generate()
if err != nil {
th.t.Fatalf("Err: %v", err)
}
return rm
}
func (th *KustTestHarness) LoadAndRunTransformer(
config, input string) resmap.ResMap {
resMap, err := th.RunTransformer(config, input)
if err != nil {
th.t.Fatalf("Err: %v", err)
}
return resMap
}
func (th *KustTestHarness) ErrorFromLoadAndRunTransformer(
config, input string) error {
_, err := th.RunTransformer(config, input)
return err
}
func (th *KustTestHarness) RunTransformer(
config, input string) (resmap.ResMap, error) {
resMap, err := th.rf.NewResMapFromBytes([]byte(input))
if err != nil {
th.t.Fatalf("Err: %v", err)
}
return th.RunTransformerFromResMap(config, resMap)
}
func (th *KustTestHarness) RunTransformerFromResMap(
config string, resMap resmap.ResMap) (resmap.ResMap, error) {
transConfig, err := th.rf.RF().FromBytes([]byte(config))
if err != nil {
th.t.Fatalf("Err: %v", err)
}
g, err := th.pl.LoadTransformer(
th.ldr, valtest_test.MakeFakeValidator(), transConfig)
if err != nil {
return nil, err
}
err = g.Transform(resMap)
return resMap, err
}
func tabToSpace(input string) string {
var result []string
for _, i := range input {
if i == 9 {
result = append(result, " ")
} else {
result = append(result, string(i))
}
}
return strings.Join(result, "")
}
func convertToArray(x string) ([]string, int) {
a := strings.Split(strings.TrimSuffix(x, "\n"), "\n")
maxLen := 0
for i, v := range a {
z := tabToSpace(v)
if len(z) > maxLen {
maxLen = len(z)
}
a[i] = z
}
return a, maxLen
}
func hint(a, b string) string {
if a == b {
return " "
}
return "X"
}
func (th *KustTestHarness) AssertActualEqualsExpected(
m resmap.ResMap, expected string) {
th.AssertActualEqualsExpectedWithTweak(m, nil, expected)
}
func (th *KustTestHarness) AssertActualEqualsExpectedWithTweak(
m resmap.ResMap, tweaker func([]byte) []byte, expected string) {
if m == nil {
th.t.Fatalf("Map should not be nil.")
}
// Ignore leading linefeed in expected value
// to ease readability of tests.
if len(expected) > 0 && expected[0] == 10 {
expected = expected[1:]
}
actual, err := m.AsYaml()
if err != nil {
th.t.Fatalf("Unexpected err: %v", err)
}
if tweaker != nil {
actual = tweaker(actual)
}
if string(actual) != expected {
th.reportDiffAndFail(actual, expected)
}
}
// Pretty printing of file differences.
func (th *KustTestHarness) reportDiffAndFail(actual []byte, expected string) {
sE, maxLen := convertToArray(expected)
sA, _ := convertToArray(string(actual))
fmt.Println("===== ACTUAL BEGIN ========================================")
fmt.Print(string(actual))
fmt.Println("===== ACTUAL END ==========================================")
format := fmt.Sprintf("%%s %%-%ds %%s\n", maxLen+4)
limit := 0
if len(sE) < len(sA) {
limit = len(sE)
} else {
limit = len(sA)
}
fmt.Printf(format, " ", "EXPECTED", "ACTUAL")
fmt.Printf(format, " ", "--------", "------")
for i := 0; i < limit; i++ {
fmt.Printf(format, hint(sE[i], sA[i]), sE[i], sA[i])
}
if len(sE) < len(sA) {
for i := len(sE); i < len(sA); i++ {
fmt.Printf(format, "X", "", sA[i])
}
} else {
for i := len(sA); i < len(sE); i++ {
fmt.Printf(format, "X", sE[i], "")
}
}
th.t.Fatalf("Expected not equal to actual")
}

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