mirror of https://github.com/kyverno/chainsaw.git
Compare commits
207 Commits
main
...
v0.2.7-bet
Author | SHA1 | Date |
---|---|---|
|
0bf667cdc7 | |
|
cdc5be8fb0 | |
|
8efda7f9a1 | |
|
a7b93a6cda | |
|
8a48313717 | |
|
2a2bd7a808 | |
|
0bcb6b4e0c | |
|
7b854d009b | |
|
0365dee1ab | |
|
ea7886a85c | |
|
8e2ba663f2 | |
|
7dfa881538 | |
|
792de8a1d1 | |
|
62539800f0 | |
|
6f2a18b88f | |
|
f0af1aae8e | |
|
60078c01b9 | |
|
48a338f5cb | |
|
8002960436 | |
|
437c781cab | |
|
18899b42b0 | |
|
39ca8895a5 | |
|
2811d18080 | |
|
0c5fae8e97 | |
|
7d1727148e | |
|
d78dca6886 | |
|
310302dc22 | |
|
63d0e49c68 | |
|
7374cf7111 | |
|
b13553b948 | |
|
91ca4dc0e0 | |
|
0d26b59ee6 | |
|
9951fe49ae | |
|
15cebcb4f0 | |
|
4fd2081054 | |
|
4fec1e5954 | |
|
3c91d0daa3 | |
|
d23688208c | |
|
bf8ffe7467 | |
|
6d5444a027 | |
|
216cd86837 | |
|
82b2504e93 | |
|
813e10e9fd | |
|
0805301f6a | |
|
99373ca197 | |
|
4b42a99474 | |
|
362749b645 | |
|
f6d484ed83 | |
|
60545e5b54 | |
|
55d5bb8ace | |
|
2c097c4087 | |
|
05ba99f6e6 | |
|
ee6520bf95 | |
|
0fdf5cddd9 | |
|
423692c22d | |
|
013ec08958 | |
|
ee8e1f1825 | |
|
7a241ad029 | |
|
4a82481aab | |
|
b305f4f348 | |
|
f1e9450194 | |
|
aed1f4307b | |
|
56f7b12c31 | |
|
558ab42ade | |
|
60623e67fc | |
|
093c9e37b0 | |
|
18d99b5e9f | |
|
fa19a76cf7 | |
|
9b05a247d5 | |
|
a27c25512a | |
|
a99022371b | |
|
e337ce6c77 | |
|
a215bb2ef4 | |
|
6f81e73441 | |
|
be87640044 | |
|
05aefe91df | |
|
a301cb7c9c | |
|
dc507c2315 | |
|
bac32f71fd | |
|
bcbff46a1e | |
|
94d92efe85 | |
|
ea600f38a7 | |
|
fd4609ddc6 | |
|
b70ab1e301 | |
|
27971133cb | |
|
26589f3206 | |
|
de919e9612 | |
|
07eb449842 | |
|
cf2c77e95c | |
|
20e426e34f | |
|
9ba295143d | |
|
64bd2fe1b7 | |
|
0514dc2d38 | |
|
693c0d9c16 | |
|
5e45e98ab0 | |
|
a5a8d5c53e | |
|
e0abec8381 | |
|
46d6e5e105 | |
|
bd0bba7ef5 | |
|
31c043659a | |
|
8fa8726974 | |
|
b53fbef960 | |
|
79749433c4 | |
|
082e83eb41 | |
|
a26c3f3cea | |
|
f17e00fd68 | |
|
231ea9a79c | |
|
fe176c0000 | |
|
f5eec08361 | |
|
13a0cf9082 | |
|
08787c49df | |
|
6a0605684f | |
|
0c62ea7eb1 | |
|
68c3faaaa7 | |
|
7431f1c37b | |
|
ce155eeae5 | |
|
42ee5aaa77 | |
|
8bd9b98394 | |
|
afcb015385 | |
|
bcfd85a2f0 | |
|
a5732f01bc | |
|
44b22d0e36 | |
|
6773dc8cd3 | |
|
8bed4698ac | |
|
1c5e38e88d | |
|
180ae170ee | |
|
eefb4482df | |
|
384132c04d | |
|
63c0b6a5d7 | |
|
78b71a0eef | |
|
e80ebb20a4 | |
|
feb61e03fa | |
|
38dc40a360 | |
|
1d4741a01c | |
|
35e0abe471 | |
|
56bf5af759 | |
|
fa6ba2e721 | |
|
99f37cadd2 | |
|
3679a1dd43 | |
|
02ec44faf9 | |
|
f3fd620429 | |
|
78a1d00f05 | |
|
f27c7756de | |
|
955eabef77 | |
|
9fabf9c33f | |
|
4fe68214e4 | |
|
f91cb71a43 | |
|
0b235f4851 | |
|
77ae277e86 | |
|
50e5a45b85 | |
|
90176eb538 | |
|
da759b6b2b | |
|
7771f24a27 | |
|
649f593f0a | |
|
119d34696b | |
|
9585468a14 | |
|
e968e662ba | |
|
ed0bdae4bc | |
|
0bae442d66 | |
|
7613418576 | |
|
010db9c13b | |
|
29ebd16a57 | |
|
f9065d761f | |
|
6db661cf41 | |
|
218e978bd4 | |
|
23a5913303 | |
|
efb3eb4ec0 | |
|
5449554481 | |
|
4915642163 | |
|
39adbf6274 | |
|
c8fad0663b | |
|
57d9440577 | |
|
6be49603ec | |
|
534afdaf90 | |
|
b70a6ce0c1 | |
|
fd0339b146 | |
|
584ecf7f7b | |
|
6b8c3bd757 | |
|
661554179e | |
|
6bb2b2e6e1 | |
|
c7a4964904 | |
|
596041226a | |
|
0734d549f5 | |
|
09792c70de | |
|
967bf17146 | |
|
8fb7732137 | |
|
f073726899 | |
|
6c60e5a3d9 | |
|
3c6932648d | |
|
7ff7ea7488 | |
|
ed0cc751fb | |
|
363b246e91 | |
|
48b069b499 | |
|
0ae5dd936f | |
|
dcc6d45e50 | |
|
97a925baf9 | |
|
037f62bdd8 | |
|
a6082dbe7d | |
|
fa8ddf5369 | |
|
1bf3caf7df | |
|
bd765c8fa9 | |
|
a38de0f688 | |
|
c4efea83f1 | |
|
382d7c6beb | |
|
931fd161d9 | |
|
453007813e | |
|
5a17bd4e96 |
|
@ -81,13 +81,6 @@ spec:
|
|||
description: Binding represents a key/value set as a binding
|
||||
in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -103,10 +96,11 @@ spec:
|
|||
check:
|
||||
description: Check is an assertion tree to validate the
|
||||
operation outcome.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will be
|
||||
inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -135,13 +129,6 @@ spec:
|
|||
description: Binding represents a key/value set as a binding
|
||||
in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -161,15 +148,9 @@ spec:
|
|||
a match to determine if the binding must be considered
|
||||
or not.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
match:
|
||||
description: Match defines the matching statement.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
|
@ -183,10 +164,6 @@ spec:
|
|||
- value
|
||||
type: object
|
||||
type: array
|
||||
skipCommandOutput:
|
||||
description: SkipCommandOutput removes the command from
|
||||
the output logs.
|
||||
type: boolean
|
||||
skipLogOutput:
|
||||
description: SkipLogOutput removes the output from the command.
|
||||
Useful for sensitive logs or to reduce noise.
|
||||
|
@ -195,19 +172,9 @@ spec:
|
|||
description: Timeout for the operation. Overrides the global
|
||||
timeout set in the Configuration.
|
||||
type: string
|
||||
workDir:
|
||||
description: WorkDir is the working directory for command.
|
||||
type: string
|
||||
required:
|
||||
- entrypoint
|
||||
type: object
|
||||
compiler:
|
||||
description: Compiler defines the default compiler to use when
|
||||
evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
delete:
|
||||
description: Delete represents a deletion operation.
|
||||
not:
|
||||
|
@ -221,13 +188,6 @@ spec:
|
|||
description: Binding represents a key/value set as a binding
|
||||
in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -241,8 +201,8 @@ spec:
|
|||
type: object
|
||||
type: array
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will be
|
||||
inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -282,9 +242,11 @@ spec:
|
|||
properties:
|
||||
check:
|
||||
description: Check defines the verification statement.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
match:
|
||||
description: Match defines the matching statement.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
required:
|
||||
- check
|
||||
|
@ -347,8 +309,8 @@ spec:
|
|||
description: API version of the referent.
|
||||
type: string
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will be
|
||||
inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -409,8 +371,8 @@ spec:
|
|||
- selector
|
||||
properties:
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will be
|
||||
inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -464,8 +426,8 @@ spec:
|
|||
description: API version of the referent.
|
||||
type: string
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will be
|
||||
inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -524,8 +486,8 @@ spec:
|
|||
- selector
|
||||
properties:
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will be
|
||||
inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -582,13 +544,6 @@ spec:
|
|||
description: Binding represents a key/value set as a binding
|
||||
in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -604,10 +559,11 @@ spec:
|
|||
check:
|
||||
description: Check is an assertion tree to validate the
|
||||
operation outcome.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will be
|
||||
inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -637,13 +593,6 @@ spec:
|
|||
description: Binding represents a key/value set as a binding
|
||||
in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -663,15 +612,9 @@ spec:
|
|||
a match to determine if the binding must be considered
|
||||
or not.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
match:
|
||||
description: Match defines the matching statement.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
|
@ -685,10 +628,6 @@ spec:
|
|||
- value
|
||||
type: object
|
||||
type: array
|
||||
skipCommandOutput:
|
||||
description: SkipCommandOutput removes the command from
|
||||
the output logs.
|
||||
type: boolean
|
||||
skipLogOutput:
|
||||
description: SkipLogOutput removes the output from the command.
|
||||
Useful for sensitive logs or to reduce noise.
|
||||
|
@ -697,9 +636,6 @@ spec:
|
|||
description: Timeout for the operation. Overrides the global
|
||||
timeout set in the Configuration.
|
||||
type: string
|
||||
workDir:
|
||||
description: WorkDir is the working directory for script.
|
||||
type: string
|
||||
type: object
|
||||
sleep:
|
||||
description: Sleep defines zzzz.
|
||||
|
@ -722,8 +658,8 @@ spec:
|
|||
description: API version of the referent.
|
||||
type: string
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will be
|
||||
inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -779,6 +715,7 @@ spec:
|
|||
type: string
|
||||
required:
|
||||
- path
|
||||
- value
|
||||
type: object
|
||||
type: object
|
||||
format:
|
||||
|
@ -831,13 +768,6 @@ spec:
|
|||
description: Clusters holds a registry to clusters to support multi-cluster
|
||||
tests.
|
||||
type: object
|
||||
compiler:
|
||||
description: Compiler defines the default compiler to use when evaluating
|
||||
expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
delayBeforeCleanup:
|
||||
description: DelayBeforeCleanup adds a delay between the time a test
|
||||
ends and the time cleanup starts.
|
||||
|
@ -881,14 +811,8 @@ spec:
|
|||
namespaceTemplate:
|
||||
description: NamespaceTemplate defines a template to create the test
|
||||
namespace.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
namespaceTemplateCompiler:
|
||||
description: NamespaceTemplateCompiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
parallel:
|
||||
description: The maximum number of tests to run at once.
|
||||
format: int
|
||||
|
@ -902,14 +826,11 @@ spec:
|
|||
type: integer
|
||||
reportFormat:
|
||||
description: |-
|
||||
ReportFormat determines test report format (JSON, XML, JUNIT-TEST, JUNIT-STEP, JUNIT-OPERATION, nil) nil == no report.
|
||||
ReportFormat determines test report format (JSON|XML|nil) nil == no report.
|
||||
maps to report.Type, however we don't want generated.deepcopy to have reference to it.
|
||||
enum:
|
||||
- JSON
|
||||
- XML
|
||||
- JUNIT-TEST
|
||||
- JUNIT-STEP
|
||||
- JUNIT-OPERATION
|
||||
type: string
|
||||
reportName:
|
||||
default: chainsaw-report
|
||||
|
@ -924,7 +845,6 @@ spec:
|
|||
tests (implies SkipClusterDelete).
|
||||
type: boolean
|
||||
template:
|
||||
default: true
|
||||
description: Template determines whether resources should be considered
|
||||
for templating.
|
||||
type: boolean
|
||||
|
@ -935,32 +855,25 @@ spec:
|
|||
If no extension is provided, chainsaw will try with .yaml first and .yml if needed.
|
||||
type: string
|
||||
timeouts:
|
||||
default: {}
|
||||
description: Global timeouts configuration. Applies to all tests/test
|
||||
steps if not overridden.
|
||||
properties:
|
||||
apply:
|
||||
default: 5s
|
||||
description: Apply defines the timeout for the apply operation
|
||||
type: string
|
||||
assert:
|
||||
default: 30s
|
||||
description: Assert defines the timeout for the assert operation
|
||||
type: string
|
||||
cleanup:
|
||||
default: 30s
|
||||
description: Cleanup defines the timeout for the cleanup operation
|
||||
type: string
|
||||
delete:
|
||||
default: 15s
|
||||
description: Delete defines the timeout for the delete operation
|
||||
type: string
|
||||
error:
|
||||
default: 30s
|
||||
description: Error defines the timeout for the error operation
|
||||
type: string
|
||||
exec:
|
||||
default: 5s
|
||||
description: Exec defines the timeout for exec operations
|
||||
type: string
|
||||
type: object
|
||||
|
@ -1108,13 +1021,6 @@ spec:
|
|||
description: Binding represents a key/value set as
|
||||
a binding in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -1130,10 +1036,11 @@ spec:
|
|||
check:
|
||||
description: Check is an assertion tree to validate
|
||||
the operation outcome.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will
|
||||
be inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -1163,13 +1070,6 @@ spec:
|
|||
description: Binding represents a key/value set as
|
||||
a binding in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -1189,15 +1089,9 @@ spec:
|
|||
a match to determine if the binding must be considered
|
||||
or not.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
match:
|
||||
description: Match defines the matching statement.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
|
@ -1211,10 +1105,6 @@ spec:
|
|||
- value
|
||||
type: object
|
||||
type: array
|
||||
skipCommandOutput:
|
||||
description: SkipCommandOutput removes the command from
|
||||
the output logs.
|
||||
type: boolean
|
||||
skipLogOutput:
|
||||
description: SkipLogOutput removes the output from the
|
||||
command. Useful for sensitive logs or to reduce noise.
|
||||
|
@ -1223,19 +1113,9 @@ spec:
|
|||
description: Timeout for the operation. Overrides the
|
||||
global timeout set in the Configuration.
|
||||
type: string
|
||||
workDir:
|
||||
description: WorkDir is the working directory for command.
|
||||
type: string
|
||||
required:
|
||||
- entrypoint
|
||||
type: object
|
||||
compiler:
|
||||
description: Compiler defines the default compiler to use
|
||||
when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
delete:
|
||||
description: Delete represents a deletion operation.
|
||||
not:
|
||||
|
@ -1249,13 +1129,6 @@ spec:
|
|||
description: Binding represents a key/value set as
|
||||
a binding in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -1269,8 +1142,8 @@ spec:
|
|||
type: object
|
||||
type: array
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will
|
||||
be inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -1310,9 +1183,11 @@ spec:
|
|||
properties:
|
||||
check:
|
||||
description: Check defines the verification statement.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
match:
|
||||
description: Match defines the matching statement.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
required:
|
||||
- check
|
||||
|
@ -1376,8 +1251,8 @@ spec:
|
|||
description: API version of the referent.
|
||||
type: string
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will
|
||||
be inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -1438,8 +1313,8 @@ spec:
|
|||
- selector
|
||||
properties:
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will
|
||||
be inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -1494,8 +1369,8 @@ spec:
|
|||
description: API version of the referent.
|
||||
type: string
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will
|
||||
be inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -1555,8 +1430,8 @@ spec:
|
|||
- selector
|
||||
properties:
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will
|
||||
be inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -1613,13 +1488,6 @@ spec:
|
|||
description: Binding represents a key/value set as
|
||||
a binding in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -1635,10 +1503,11 @@ spec:
|
|||
check:
|
||||
description: Check is an assertion tree to validate
|
||||
the operation outcome.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will
|
||||
be inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -1668,13 +1537,6 @@ spec:
|
|||
description: Binding represents a key/value set as
|
||||
a binding in an executing test.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
pattern: ^(?:\w+|\(.+\))$
|
||||
|
@ -1694,15 +1556,9 @@ spec:
|
|||
a match to determine if the binding must be considered
|
||||
or not.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler
|
||||
to use when evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
match:
|
||||
description: Match defines the matching statement.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
name:
|
||||
description: Name the name of the binding.
|
||||
|
@ -1716,10 +1572,6 @@ spec:
|
|||
- value
|
||||
type: object
|
||||
type: array
|
||||
skipCommandOutput:
|
||||
description: SkipCommandOutput removes the command from
|
||||
the output logs.
|
||||
type: boolean
|
||||
skipLogOutput:
|
||||
description: SkipLogOutput removes the output from the
|
||||
command. Useful for sensitive logs or to reduce noise.
|
||||
|
@ -1728,9 +1580,6 @@ spec:
|
|||
description: Timeout for the operation. Overrides the
|
||||
global timeout set in the Configuration.
|
||||
type: string
|
||||
workDir:
|
||||
description: WorkDir is the working directory for script.
|
||||
type: string
|
||||
type: object
|
||||
sleep:
|
||||
description: Sleep defines zzzz.
|
||||
|
@ -1753,8 +1602,8 @@ spec:
|
|||
description: API version of the referent.
|
||||
type: string
|
||||
cluster:
|
||||
description: Cluster defines the target cluster (will
|
||||
be inherited if not specified).
|
||||
description: Cluster defines the target cluster (default
|
||||
cluster will be used if not specified and/or overridden).
|
||||
type: string
|
||||
clusters:
|
||||
additionalProperties:
|
||||
|
@ -1811,6 +1660,7 @@ spec:
|
|||
type: string
|
||||
required:
|
||||
- path
|
||||
- value
|
||||
type: object
|
||||
type: object
|
||||
format:
|
||||
|
@ -1877,13 +1727,6 @@ spec:
|
|||
description: Namespace contains properties for the namespace to use
|
||||
for tests.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler to use when
|
||||
evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
name:
|
||||
description: |-
|
||||
Name defines the namespace to use for tests.
|
||||
|
@ -1892,6 +1735,7 @@ spec:
|
|||
type: string
|
||||
template:
|
||||
description: Template defines a template to create the test namespace.
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
report:
|
||||
|
@ -1899,14 +1743,10 @@ spec:
|
|||
properties:
|
||||
format:
|
||||
default: JSON
|
||||
description: ReportFormat determines test report format (JSON,
|
||||
XML, JUNIT-TEST, JUNIT-STEP, JUNIT-OPERATION).
|
||||
description: ReportFormat determines test report format (JSON|XML).
|
||||
enum:
|
||||
- JSON
|
||||
- XML
|
||||
- JUNIT-TEST
|
||||
- JUNIT-STEP
|
||||
- JUNIT-OPERATION
|
||||
type: string
|
||||
name:
|
||||
default: chainsaw-report
|
||||
|
@ -1921,13 +1761,6 @@ spec:
|
|||
default: {}
|
||||
description: Templating contains the templating config.
|
||||
properties:
|
||||
compiler:
|
||||
description: Compiler defines the default compiler to use when
|
||||
evaluating expressions.
|
||||
enum:
|
||||
- jp
|
||||
- cel
|
||||
type: string
|
||||
enabled:
|
||||
default: true
|
||||
description: Enabled determines whether resources should be considered
|
||||
|
@ -1940,27 +1773,21 @@ spec:
|
|||
steps if not overridden.
|
||||
properties:
|
||||
apply:
|
||||
default: 5s
|
||||
description: Apply defines the timeout for the apply operation
|
||||
type: string
|
||||
assert:
|
||||
default: 30s
|
||||
description: Assert defines the timeout for the assert operation
|
||||
type: string
|
||||
cleanup:
|
||||
default: 30s
|
||||
description: Cleanup defines the timeout for the cleanup operation
|
||||
type: string
|
||||
delete:
|
||||
default: 15s
|
||||
description: Delete defines the timeout for the delete operation
|
||||
type: string
|
||||
error:
|
||||
default: 30s
|
||||
description: Error defines the timeout for the error operation
|
||||
type: string
|
||||
exec:
|
||||
default: 5s
|
||||
description: Exec defines the timeout for exec operations
|
||||
type: string
|
||||
type: object
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -14,12 +14,6 @@ body:
|
|||
label: chainsaw version Version
|
||||
description: What version of chainsaw are you running?
|
||||
options:
|
||||
- v0.2.12
|
||||
- v0.2.11
|
||||
- v0.2.10
|
||||
- v0.2.9
|
||||
- v0.2.8
|
||||
- v0.2.7
|
||||
- v0.2.6
|
||||
- v0.2.5
|
||||
- v0.2.4
|
||||
|
|
|
@ -23,12 +23,6 @@ body:
|
|||
label: chainsaw version Version
|
||||
description: What version of chainsaw are you running?
|
||||
options:
|
||||
- v0.2.12
|
||||
- v0.2.11
|
||||
- v0.2.10
|
||||
- v0.2.9
|
||||
- v0.2.8
|
||||
- v0.2.7
|
||||
- v0.2.6
|
||||
- v0.2.5
|
||||
- v0.2.4
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: gomod
|
||||
directories:
|
||||
- /
|
||||
- /hack/controller-gen/
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
- package-ecosystem: github-actions
|
||||
|
|
|
@ -23,9 +23,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Ensure SHA pinned actions
|
||||
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@fc87bb5b5a97953d987372e74478de634726b3e5 # v3.0.25
|
||||
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@b88cd0aad2c36a63e42c71f81cb1958fed95ac87 # v3.0.10
|
||||
with:
|
||||
# slsa-github-generator requires using a semver tag for reusable workflows.
|
||||
# See: https://github.com/slsa-framework/slsa-github-generator#referencing-slsa-builders-and-generators
|
||||
|
|
|
@ -23,9 +23,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
|
|
|
@ -25,11 +25,11 @@ jobs:
|
|||
security-events: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Run Trivy vulnerability scanner in repo mode
|
||||
uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 # v0.32.0
|
||||
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # v0.24.0
|
||||
with:
|
||||
scan-type: fs
|
||||
ignore-unfixed: false
|
||||
|
@ -39,10 +39,8 @@ jobs:
|
|||
scanners: vuln,secret
|
||||
exit-code: '0'
|
||||
vuln-type: os,library
|
||||
env:
|
||||
TRIVY_DB_REPOSITORY: 'public.ecr.aws/aquasecurity/trivy-db:2'
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.5
|
||||
uses: github/codeql-action/upload-sarif@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3.25.12
|
||||
with:
|
||||
sarif_file: trivy-results.sarif
|
||||
category: code
|
||||
category: code
|
|
@ -20,9 +20,9 @@ jobs:
|
|||
contents: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
|
|
|
@ -23,9 +23,9 @@ jobs:
|
|||
version_extractor_regex: '^docs-v(.*)$'
|
||||
- name: Checkout
|
||||
if: ${{ steps.semver.outputs.prerelease == '' }}
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
if: ${{ steps.semver.outputs.prerelease == '' }}
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
|
|
@ -23,13 +23,13 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
|
||||
uses: golangci/golangci-lint-action@a4f60bb28d35aeee14e6880718e0c85ff1882e64 # v3.7.1
|
||||
with:
|
||||
skip-cache: true
|
||||
|
|
|
@ -44,6 +44,7 @@ concurrency:
|
|||
jobs:
|
||||
check-semantic-pr:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.actor != 'gcp-cherry-pick-bot' }}
|
||||
steps:
|
||||
- name: Validate Pull Request
|
||||
uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017
|
||||
|
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
docker-images: true
|
||||
swap-storage: false
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all tags
|
||||
|
@ -41,19 +41,19 @@ jobs:
|
|||
set -e
|
||||
git fetch --force --tags
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
|
||||
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
|
||||
- name: Install Syft
|
||||
uses: anchore/sbom-action/download-syft@7b36ad622f042cab6f59a75c2ac24ccb256e9b45 # v0.20.4
|
||||
uses: anchore/sbom-action/download-syft@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 # v0.17.0
|
||||
- name: Install Ko
|
||||
uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
|
||||
uses: ko-build/setup-ko@3aebd0597dc1e9d1a26bcfdb7cbeb19c131d3037 # v0.7
|
||||
- name: Run GoReleaser
|
||||
id: goreleaser
|
||||
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
|
||||
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: latest
|
||||
|
@ -61,14 +61,14 @@ jobs:
|
|||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload artifacts.json
|
||||
uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # 2.11.2
|
||||
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # 2.9.0
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: dist/artifacts.json
|
||||
asset_name: artifacts.json
|
||||
tag: ${{ github.ref }}
|
||||
- name: Upload metadata.json
|
||||
uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # 2.11.2
|
||||
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # 2.9.0
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: dist/metadata.json
|
||||
|
@ -102,7 +102,7 @@ jobs:
|
|||
actions: read
|
||||
id-token: write
|
||||
contents: write
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
|
||||
with:
|
||||
base64-subjects: "${{ needs.goreleaser.outputs.hashes }}"
|
||||
upload-assets: true
|
||||
|
@ -114,7 +114,7 @@ jobs:
|
|||
actions: read
|
||||
id-token: write
|
||||
packages: write
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
|
||||
with:
|
||||
image: ${{ needs.goreleaser.outputs.image }}
|
||||
digest: ${{ needs.goreleaser.outputs.digest }}
|
||||
|
|
|
@ -23,9 +23,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
|
@ -38,7 +38,7 @@ jobs:
|
|||
set -e
|
||||
make tests
|
||||
- name: Upload coverage
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
|
||||
with:
|
||||
name: coverage.out
|
||||
path: coverage.out
|
||||
|
@ -50,12 +50,14 @@ jobs:
|
|||
- unit-tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Download coverage
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: coverage.out
|
||||
- name: Upload Report to Codecov
|
||||
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
|
||||
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
||||
with:
|
||||
files: ./coverage.out
|
||||
fail_ci_if_error: true
|
||||
|
@ -67,9 +69,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
|
@ -82,33 +84,18 @@ jobs:
|
|||
set -e
|
||||
make e2e-tests
|
||||
|
||||
e2e-tests-no-cluster:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
- name: Run tests
|
||||
run: |
|
||||
set -e
|
||||
make e2e-tests-no-cluster
|
||||
|
||||
e2e-test-ko:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
- name: Install ko
|
||||
uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d #v0.9
|
||||
uses: ko-build/setup-ko@3aebd0597dc1e9d1a26bcfdb7cbeb19c131d3037 #v0.7
|
||||
- name: Create test cluster
|
||||
run: |
|
||||
set -e
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
version: "2"
|
||||
linters:
|
||||
enable:
|
||||
- asasalint
|
||||
|
@ -6,49 +5,46 @@ linters:
|
|||
- bidichk
|
||||
- bodyclose
|
||||
- containedctx
|
||||
- copyloopvar
|
||||
- decorder
|
||||
- dogsled
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errname
|
||||
- exportloopref
|
||||
- gci
|
||||
- gochecknoinits
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- grouper
|
||||
- importas
|
||||
- ineffassign
|
||||
- makezero
|
||||
- misspell
|
||||
- noctx
|
||||
- nolintlint
|
||||
- nosprintfhostport
|
||||
# - paralleltest
|
||||
- staticcheck
|
||||
- tenv
|
||||
- thelper
|
||||
- tparallel
|
||||
- typecheck
|
||||
- unconvert
|
||||
- usetesting
|
||||
- unused
|
||||
- wastedassign
|
||||
- whitespace
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- .+\.generated.go
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gci
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- .+\.generated.go
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
||||
run:
|
||||
timeout: 15m
|
||||
|
||||
output:
|
||||
sort-results: true
|
||||
|
||||
issues:
|
||||
exclude-files:
|
||||
- ".+\\.generated.go"
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
version: 2
|
||||
|
||||
before:
|
||||
hooks:
|
||||
- go mod tidy
|
||||
|
@ -17,30 +15,6 @@ builds:
|
|||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w -X github.com/kyverno/chainsaw/pkg/version.BuildVersion={{ .Version }}
|
||||
- id: s390x
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
- s390x
|
||||
binary: chainsaw
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w -X github.com/kyverno/chainsaw/pkg/version.BuildVersion={{ .Version }}
|
||||
- id: ppc64le
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
- ppc64le
|
||||
binary: chainsaw
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w -X github.com/kyverno/chainsaw/pkg/version.BuildVersion={{ .Version }}
|
||||
|
||||
kos:
|
||||
- build: chainsaw
|
||||
|
@ -108,7 +82,7 @@ sboms:
|
|||
artifacts: source
|
||||
|
||||
snapshot:
|
||||
version_template: '{{ incpatch .Version }}-next'
|
||||
name_template: '{{ incpatch .Version }}-next'
|
||||
|
||||
release:
|
||||
prerelease: auto
|
||||
|
|
|
@ -19,7 +19,3 @@ Release notes for `TODO`.
|
|||
|
||||
## 🎸 Misc 🎸
|
||||
-->
|
||||
|
||||
## 💫 New features 💫
|
||||
|
||||
- Continue tests when an error happens when computing the test name
|
|
@ -1,24 +0,0 @@
|
|||
# Release notes
|
||||
|
||||
Release notes for `v0.2.10`.
|
||||
|
||||
## 💫 New features 💫
|
||||
|
||||
- Added bindings support when referencing step templates
|
||||
- Restructured the reports system
|
||||
- Added reports in JSON format back
|
||||
- Added new JUnit report formats with different granularity (`JUNIT-TEST`, `JUNIT-STEP`, `JUNIT-OPERATION`)
|
||||
- `XML` report format should be considered deprecated and replaced with one of the `JUNIT-*` format
|
||||
|
||||
## 🔧 Fixes 🔧
|
||||
|
||||
- Fixed default report name not set correctly
|
||||
- Made `template` required when referencing a step template
|
||||
|
||||
## 📚 Docs 📚
|
||||
|
||||
- Started a JMESPath function example page in the docs (only `x_k8s_get` is available at this time)
|
||||
|
||||
## 🎸 Misc 🎸
|
||||
|
||||
- Removed test `v1alpha2` API for now
|
|
@ -1,17 +0,0 @@
|
|||
# Release notes
|
||||
|
||||
Release notes for `v0.2.11`.
|
||||
|
||||
## 💫 New features 💫
|
||||
|
||||
- Added CEL support everywhere (bindings, assertion trees, projection trees, outputs...)
|
||||
- Added test sharding support
|
||||
|
||||
## 🔧 Fixes 🔧
|
||||
|
||||
- Fixed exit code when failing in root test run
|
||||
- Fixed `--no-cluster` flag not working
|
||||
|
||||
## 📚 Docs 📚
|
||||
|
||||
- Added most JMESPath functions docs and examples
|
|
@ -1,15 +0,0 @@
|
|||
# Release notes
|
||||
|
||||
Release notes for `v0.2.12`.
|
||||
|
||||
## 💫 New features 💫
|
||||
|
||||
- Registered Kubernetes CEL libs, optional types, and various other std libs
|
||||
- Support conditions in labels in assertion templates
|
||||
- Added `skipCommandOutput` support to not log the `command` and `script` being executed
|
||||
|
||||
## 🔧 Fixes 🔧
|
||||
|
||||
- Allow escaping dollar sign in `command` and `script`
|
||||
- Fixed `chainsaw build docs` rendering invalid yaml
|
||||
- Fixed step template bindings registered in the wrong order
|
|
@ -1,18 +0,0 @@
|
|||
# Release notes
|
||||
|
||||
Release notes for `v0.2.7`.
|
||||
|
||||
## 💫 New features 💫
|
||||
|
||||
- Added initial `TestTemplate` support to allow defining steps in separate files and reusing them across tests
|
||||
- Replaced programmatic validation with schema-based validation
|
||||
- Better generated JSON schemas based on OpenAPI v3 instead of v2
|
||||
|
||||
## 🔧 Fixes 🔧
|
||||
|
||||
- Fixed incorrect `null` vs empty object comparison in assertion operations
|
||||
|
||||
## 📚 Docs 📚
|
||||
|
||||
- Added detailed community pages to the website website
|
||||
- Added a CODE_OF_CONDUCT.md file in the repo
|
|
@ -1,21 +0,0 @@
|
|||
# Release notes
|
||||
|
||||
Release notes for `v0.2.8`.
|
||||
|
||||
## 💫 New features 💫
|
||||
|
||||
- Added `chainsaw renovate config` to upgrade configuration manifests to `v1alpha2`
|
||||
- Changed `cluster` in test step and actions to a pointer
|
||||
- `null` means inherit the current cluster
|
||||
- an empty string means the default cluster
|
||||
- Made default timeouts part of the schemas
|
||||
- Added support to fail fast at the test level (test will be skipped if a previous error was already reported)
|
||||
- Delay operation loading until operation execution
|
||||
- Generate strict JSON schemas
|
||||
|
||||
## 🔧 Fixes 🔧
|
||||
|
||||
- Fixed incorrect bindings when operations are run against different clusters
|
||||
- Fixed operation info built-in bindings not registered before other bindings
|
||||
- Fixed incorrect cluster client used when applying the test namespace to resources
|
||||
- Detect accessing nodes not present in the payload when traversing an assertion tree
|
|
@ -1,19 +0,0 @@
|
|||
# Release notes
|
||||
|
||||
Release notes for `v0.2.9`.
|
||||
|
||||
## 💫 New features 💫
|
||||
|
||||
- Added support for templating filenames used in operations
|
||||
- Added `ppc64le` and `s390x` binaries in release artifacts
|
||||
- Added support for Kubernetes 1.31
|
||||
- Added server side validation to validate the submitted resource
|
||||
- Added support for overriding the working directory in `command` and `script` operations
|
||||
- Compile string expressions at loading time
|
||||
- Made json path value optional in `wait` operation
|
||||
- Improved logging with `begin`, `end` and `warning` statuses
|
||||
- Added golang 1.23 support
|
||||
|
||||
## 🔧 Fixes 🔧
|
||||
|
||||
- Fixed configuration `v1alpha2` lint command
|
|
@ -96,7 +96,6 @@
|
|||
],
|
||||
"default": ""
|
||||
},
|
||||
"x-kubernetes-list-type": "set",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
},
|
||||
"generateName": {
|
||||
|
@ -204,12 +203,10 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"x-kubernetes-list-type": "atomic"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"description": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names",
|
||||
|
@ -282,15 +279,10 @@
|
|||
"default": ""
|
||||
}
|
||||
},
|
||||
"x-kubernetes-map-type": "atomic",
|
||||
"additionalProperties": false
|
||||
"x-kubernetes-map-type": "atomic"
|
||||
}
|
||||
]
|
||||
},
|
||||
"x-kubernetes-list-map-keys": [
|
||||
"uid"
|
||||
],
|
||||
"x-kubernetes-list-type": "map",
|
||||
"x-kubernetes-patch-merge-key": "uid",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
},
|
||||
|
@ -315,8 +307,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -427,17 +418,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -447,16 +427,19 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"check": {
|
||||
"description": "Check is an assertion tree to validate the operation outcome.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -489,8 +472,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"entrypoint": {
|
||||
|
@ -514,17 +496,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -534,8 +505,7 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
|
@ -555,19 +525,12 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"match": {
|
||||
"description": "Match defines the matching statement.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"name": {
|
||||
|
@ -579,17 +542,9 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"skipCommandOutput": {
|
||||
"description": "SkipCommandOutput removes the command from the output logs.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"skipLogOutput": {
|
||||
"description": "SkipLogOutput removes the output from the command. Useful for sensitive logs or to reduce noise.",
|
||||
"type": [
|
||||
|
@ -603,27 +558,8 @@
|
|||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"workDir": {
|
||||
"description": "WorkDir is the working directory for command.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete represents a deletion operation.",
|
||||
|
@ -655,17 +591,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -675,12 +600,11 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -713,8 +637,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"deletionPropagationPolicy": {
|
||||
|
@ -747,14 +670,18 @@
|
|||
"properties": {
|
||||
"check": {
|
||||
"description": "Check defines the verification statement.",
|
||||
"type": "object",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"match": {
|
||||
"description": "Match defines the matching statement.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"file": {
|
||||
|
@ -810,8 +737,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"description": "Template determines whether resources should be considered for templating.",
|
||||
|
@ -827,8 +753,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"describe": {
|
||||
"description": "Describe determines the resource describe collector to execute.",
|
||||
|
@ -852,7 +777,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -885,8 +810,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
|
@ -928,8 +852,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"description": "Description contains a description of the operation.",
|
||||
|
@ -952,7 +875,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -985,8 +908,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
|
@ -1025,8 +947,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"description": "Get determines the resource get collector to execute.",
|
||||
|
@ -1050,7 +971,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1083,8 +1004,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
|
@ -1127,8 +1047,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"podLogs": {
|
||||
"description": "PodLogs determines the pod logs collector to execute.",
|
||||
|
@ -1144,7 +1063,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1177,8 +1096,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"container": {
|
||||
|
@ -1223,8 +1141,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"script": {
|
||||
"description": "Script defines a script to run.",
|
||||
|
@ -1250,17 +1167,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -1270,16 +1176,19 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"check": {
|
||||
"description": "Check is an assertion tree to validate the operation outcome.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1312,8 +1221,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
|
@ -1340,17 +1248,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -1360,8 +1257,7 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
|
@ -1381,19 +1277,12 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"match": {
|
||||
"description": "Match defines the matching statement.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"name": {
|
||||
|
@ -1405,17 +1294,9 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"skipCommandOutput": {
|
||||
"description": "SkipCommandOutput removes the command from the output logs.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"skipLogOutput": {
|
||||
"description": "SkipLogOutput removes the output from the command. Useful for sensitive logs or to reduce noise.",
|
||||
"type": [
|
||||
|
@ -1429,16 +1310,8 @@
|
|||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"workDir": {
|
||||
"description": "WorkDir is the working directory for script.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"sleep": {
|
||||
"description": "Sleep defines zzzz.",
|
||||
|
@ -1454,8 +1327,7 @@
|
|||
"description": "Duration is the delay used for sleeping.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"wait": {
|
||||
"description": "Wait determines the resource wait collector to execute.",
|
||||
|
@ -1480,7 +1352,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1513,8 +1385,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"for": {
|
||||
|
@ -1542,8 +1413,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"deletion": {
|
||||
"description": "Deletion specifies parameters for waiting on a resource's deletion.",
|
||||
|
@ -1559,7 +1429,8 @@
|
|||
"null"
|
||||
],
|
||||
"required": [
|
||||
"path"
|
||||
"path",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
|
@ -1568,16 +1439,11 @@
|
|||
},
|
||||
"value": {
|
||||
"description": "Value defines the expected value to wait for, e.g., \"Running\".",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
"description": "Format determines the output format (json or yaml).",
|
||||
|
@ -1619,11 +1485,9 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"clusters": {
|
||||
|
@ -1653,21 +1517,9 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"delayBeforeCleanup": {
|
||||
"description": "DelayBeforeCleanup adds a delay between the time a test ends and the time cleanup starts.",
|
||||
"type": [
|
||||
|
@ -1732,18 +1584,11 @@
|
|||
},
|
||||
"namespaceTemplate": {
|
||||
"description": "NamespaceTemplate defines a template to create the test namespace.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"namespaceTemplateCompiler": {
|
||||
"description": "NamespaceTemplateCompiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"parallel": {
|
||||
"description": "The maximum number of tests to run at once.",
|
||||
|
@ -1764,17 +1609,14 @@
|
|||
"minimum": 1
|
||||
},
|
||||
"reportFormat": {
|
||||
"description": "ReportFormat determines test report format (JSON, XML, JUNIT-TEST, JUNIT-STEP, JUNIT-OPERATION, nil) nil == no report.\nmaps to report.Type, however we don't want generated.deepcopy to have reference to it.",
|
||||
"description": "ReportFormat determines test report format (JSON|XML|nil) nil == no report.\nmaps to report.Type, however we don't want generated.deepcopy to have reference to it.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"JSON",
|
||||
"XML",
|
||||
"JUNIT-TEST",
|
||||
"JUNIT-STEP",
|
||||
"JUNIT-OPERATION"
|
||||
"XML"
|
||||
]
|
||||
},
|
||||
"reportName": {
|
||||
|
@ -1804,8 +1646,7 @@
|
|||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
],
|
||||
"default": true
|
||||
]
|
||||
},
|
||||
"testFile": {
|
||||
"description": "TestFile is the name of the file containing the test to run.\nIf no extension is provided, chainsaw will try with .yaml first and .yml if needed.",
|
||||
|
@ -1821,61 +1662,52 @@
|
|||
"object",
|
||||
"null"
|
||||
],
|
||||
"default": {},
|
||||
"properties": {
|
||||
"apply": {
|
||||
"description": "Apply defines the timeout for the apply operation",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "5s"
|
||||
]
|
||||
},
|
||||
"assert": {
|
||||
"description": "Assert defines the timeout for the assert operation",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "30s"
|
||||
]
|
||||
},
|
||||
"cleanup": {
|
||||
"description": "Cleanup defines the timeout for the cleanup operation",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "30s"
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete defines the timeout for the delete operation",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "15s"
|
||||
]
|
||||
},
|
||||
"error": {
|
||||
"description": "Error defines the timeout for the error operation",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "30s"
|
||||
]
|
||||
},
|
||||
"exec": {
|
||||
"description": "Exec defines the timeout for exec operations",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "5s"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-kubernetes-group-version-kind": [
|
||||
|
@ -1885,6 +1717,5 @@
|
|||
"version": "v1alpha1"
|
||||
}
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"$schema": "http://json-schema.org/schema#"
|
||||
}
|
|
@ -96,7 +96,6 @@
|
|||
],
|
||||
"default": ""
|
||||
},
|
||||
"x-kubernetes-list-type": "set",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
},
|
||||
"generateName": {
|
||||
|
@ -204,12 +203,10 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"x-kubernetes-list-type": "atomic"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"description": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names",
|
||||
|
@ -282,15 +279,10 @@
|
|||
"default": ""
|
||||
}
|
||||
},
|
||||
"x-kubernetes-map-type": "atomic",
|
||||
"additionalProperties": false
|
||||
"x-kubernetes-map-type": "atomic"
|
||||
}
|
||||
]
|
||||
},
|
||||
"x-kubernetes-list-map-keys": [
|
||||
"uid"
|
||||
],
|
||||
"x-kubernetes-list-type": "map",
|
||||
"x-kubernetes-patch-merge-key": "uid",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
},
|
||||
|
@ -315,8 +307,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -349,8 +340,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"clusters": {
|
||||
"description": "Clusters holds a registry to clusters to support multi-cluster tests.",
|
||||
|
@ -379,8 +369,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"deletion": {
|
||||
|
@ -404,8 +393,7 @@
|
|||
"Foreground"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"discovery": {
|
||||
"description": "Discovery contains tests discovery configuration.",
|
||||
|
@ -444,8 +432,7 @@
|
|||
],
|
||||
"default": "chainsaw-test"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"description": "Error contains the global error configuration.",
|
||||
|
@ -555,17 +542,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -575,16 +551,19 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"check": {
|
||||
"description": "Check is an assertion tree to validate the operation outcome.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -617,8 +596,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"entrypoint": {
|
||||
|
@ -642,17 +620,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -662,8 +629,7 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
|
@ -683,19 +649,12 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"match": {
|
||||
"description": "Match defines the matching statement.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"name": {
|
||||
|
@ -707,17 +666,9 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"skipCommandOutput": {
|
||||
"description": "SkipCommandOutput removes the command from the output logs.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"skipLogOutput": {
|
||||
"description": "SkipLogOutput removes the output from the command. Useful for sensitive logs or to reduce noise.",
|
||||
"type": [
|
||||
|
@ -731,27 +682,8 @@
|
|||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"workDir": {
|
||||
"description": "WorkDir is the working directory for command.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete represents a deletion operation.",
|
||||
|
@ -783,17 +715,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -803,12 +724,11 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -841,8 +761,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"deletionPropagationPolicy": {
|
||||
|
@ -875,14 +794,18 @@
|
|||
"properties": {
|
||||
"check": {
|
||||
"description": "Check defines the verification statement.",
|
||||
"type": "object",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"match": {
|
||||
"description": "Match defines the matching statement.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"file": {
|
||||
|
@ -938,8 +861,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"description": "Template determines whether resources should be considered for templating.",
|
||||
|
@ -955,8 +877,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"describe": {
|
||||
"description": "Describe determines the resource describe collector to execute.",
|
||||
|
@ -980,7 +901,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1013,8 +934,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
|
@ -1056,8 +976,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"description": "Description contains a description of the operation.",
|
||||
|
@ -1080,7 +999,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1113,8 +1032,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
|
@ -1153,8 +1071,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"description": "Get determines the resource get collector to execute.",
|
||||
|
@ -1178,7 +1095,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1211,8 +1128,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
|
@ -1255,8 +1171,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"podLogs": {
|
||||
"description": "PodLogs determines the pod logs collector to execute.",
|
||||
|
@ -1272,7 +1187,7 @@
|
|||
},
|
||||
"properties": {
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1305,8 +1220,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"container": {
|
||||
|
@ -1351,8 +1265,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"script": {
|
||||
"description": "Script defines a script to run.",
|
||||
|
@ -1378,17 +1291,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -1398,16 +1300,19 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"check": {
|
||||
"description": "Check is an assertion tree to validate the operation outcome.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1440,8 +1345,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
|
@ -1468,17 +1372,6 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name the name of the binding.",
|
||||
"type": "string",
|
||||
|
@ -1488,8 +1381,7 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
|
@ -1509,19 +1401,12 @@
|
|||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"match": {
|
||||
"description": "Match defines the matching statement.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"name": {
|
||||
|
@ -1533,17 +1418,9 @@
|
|||
"description": "Value value of the binding.",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"skipCommandOutput": {
|
||||
"description": "SkipCommandOutput removes the command from the output logs.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"skipLogOutput": {
|
||||
"description": "SkipLogOutput removes the output from the command. Useful for sensitive logs or to reduce noise.",
|
||||
"type": [
|
||||
|
@ -1557,16 +1434,8 @@
|
|||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"workDir": {
|
||||
"description": "WorkDir is the working directory for script.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"sleep": {
|
||||
"description": "Sleep defines zzzz.",
|
||||
|
@ -1582,8 +1451,7 @@
|
|||
"description": "Duration is the delay used for sleeping.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"wait": {
|
||||
"description": "Wait determines the resource wait collector to execute.",
|
||||
|
@ -1608,7 +1476,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster defines the target cluster (will be inherited if not specified).",
|
||||
"description": "Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1641,8 +1509,7 @@
|
|||
"description": "Kubeconfig is the path to the referenced file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"for": {
|
||||
|
@ -1670,8 +1537,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"deletion": {
|
||||
"description": "Deletion specifies parameters for waiting on a resource's deletion.",
|
||||
|
@ -1687,7 +1553,8 @@
|
|||
"null"
|
||||
],
|
||||
"required": [
|
||||
"path"
|
||||
"path",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
|
@ -1696,16 +1563,11 @@
|
|||
},
|
||||
"value": {
|
||||
"description": "Value defines the expected value to wait for, e.g., \"Running\".",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
"description": "Format determines the output format (json or yaml).",
|
||||
|
@ -1747,15 +1609,12 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"execution": {
|
||||
"description": "Execution contains tests execution configuration.",
|
||||
|
@ -1797,8 +1656,7 @@
|
|||
"format": "int",
|
||||
"minimum": 1
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"namespace": {
|
||||
"description": "Namespace contains properties for the namespace to use for tests.",
|
||||
|
@ -1808,17 +1666,6 @@
|
|||
],
|
||||
"default": {},
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name defines the namespace to use for tests.\nIf not specified, every test will execute in a random ephemeral namespace\nunless the namespace is overridden in a the test spec.",
|
||||
"type": [
|
||||
|
@ -1828,10 +1675,13 @@
|
|||
},
|
||||
"template": {
|
||||
"description": "Template defines a template to create the test namespace.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"report": {
|
||||
"description": "Report contains properties for the report.",
|
||||
|
@ -1841,7 +1691,7 @@
|
|||
],
|
||||
"properties": {
|
||||
"format": {
|
||||
"description": "ReportFormat determines test report format (JSON, XML, JUNIT-TEST, JUNIT-STEP, JUNIT-OPERATION).",
|
||||
"description": "ReportFormat determines test report format (JSON|XML).",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -1849,10 +1699,7 @@
|
|||
"default": "JSON",
|
||||
"enum": [
|
||||
"JSON",
|
||||
"XML",
|
||||
"JUNIT-TEST",
|
||||
"JUNIT-STEP",
|
||||
"JUNIT-OPERATION"
|
||||
"XML"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
|
@ -1870,8 +1717,7 @@
|
|||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"templating": {
|
||||
"description": "Templating contains the templating config.",
|
||||
|
@ -1881,17 +1727,6 @@
|
|||
],
|
||||
"default": {},
|
||||
"properties": {
|
||||
"compiler": {
|
||||
"description": "Compiler defines the default compiler to use when evaluating expressions.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"jp",
|
||||
"cel"
|
||||
]
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Enabled determines whether resources should be considered for templating.",
|
||||
"type": [
|
||||
|
@ -1900,8 +1735,7 @@
|
|||
],
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"timeouts": {
|
||||
"description": "Global timeouts configuration. Applies to all tests/test steps if not overridden.",
|
||||
|
@ -1916,54 +1750,46 @@
|
|||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "5s"
|
||||
]
|
||||
},
|
||||
"assert": {
|
||||
"description": "Assert defines the timeout for the assert operation",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "30s"
|
||||
]
|
||||
},
|
||||
"cleanup": {
|
||||
"description": "Cleanup defines the timeout for the cleanup operation",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "30s"
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete defines the timeout for the delete operation",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "15s"
|
||||
]
|
||||
},
|
||||
"error": {
|
||||
"description": "Error defines the timeout for the error operation",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "30s"
|
||||
]
|
||||
},
|
||||
"exec": {
|
||||
"description": "Exec defines the timeout for exec operations",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": "5s"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-kubernetes-group-version-kind": [
|
||||
|
@ -1973,6 +1799,5 @@
|
|||
"version": "v1alpha2"
|
||||
}
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"$schema": "http://json-schema.org/schema#"
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -16,7 +16,6 @@
|
|||
"./testdata/e2e/examples",
|
||||
"--config",
|
||||
"./testdata/e2e/config.yaml",
|
||||
"--remarshal",
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -9,7 +9,6 @@ The list of organizations that have publicly shared the usage of Chainsaw:
|
|||
| Organization | Success Story |
|
||||
|:--|:--|
|
||||
| [Keptn](https://github.com/keptn/lifecycle-toolkit)| Chainsaw replaced Kuttl, and helped us get rid of many unreadable bash scripts |
|
||||
| [OpenFeature](https://github.com/open-feature/open-feature-operator)| Chainsaw replaced Kuttl, helped us improve logging and remove native kubectl calls |
|
||||
| [Kyverno](https://kyverno.io) | Running all end to end tests for both Kyverno and the policies catalog |
|
||||
| [Nirmata](https://nirmata.com/) | Using Chainsaw extensively to test curated Kyverno policies, Kyverno Operator and other e2e internal testing |
|
||||
| [Redis-operator](https://github.com/OT-CONTAINER-KIT/redis-operator) | Chainsaw helped a lot for declarative assertion of Redis Cluster state against various e2e test |
|
||||
|
@ -21,7 +20,6 @@ The list of organizations that have publicly shared the usage of Chainsaw:
|
|||
| [Provider-ceph](https://github.com/linode/provider-ceph) | Chainsaw replaced Kuttl and made our e2e tests much more readable and easier to debug |
|
||||
| [Linode CAPI provider](https://github.com/linode/cluster-api-provider-linode) | Chainsaw replaced Kuttl and made our e2e tests much more readable and easier to debug. 🙏 @eddycharly |
|
||||
| [Linode COSI driver](https://github.com/linode/linode-cosi-driver) | Running all end to end tests for object store driver |
|
||||
| [Odigos](https://github.com/odigos-io/odigos) | Chainsaw helps us run complex e2e tests confidently, ensuring project reliability. |
|
||||
|
||||
|
||||
<!-- append the line below to the table
|
||||
|
|
67
Makefile
67
Makefile
|
@ -7,6 +7,9 @@
|
|||
GIT_SHA := $(shell git rev-parse HEAD)
|
||||
ORG ?= kyverno
|
||||
PACKAGE ?= github.com/$(ORG)/chainsaw
|
||||
GOPATH_SHIM := ${PWD}/.gopath
|
||||
PACKAGE_SHIM := $(GOPATH_SHIM)/src/$(PACKAGE)
|
||||
INPUT_DIRS := $(PACKAGE)/pkg/apis/v1alpha1,$(PACKAGE)/pkg/apis/v1alpha2
|
||||
CRDS_PATH := ${PWD}/.crds
|
||||
CLI_BIN := chainsaw
|
||||
CGO_ENABLED ?= 0
|
||||
|
@ -18,7 +21,7 @@ LD_FLAGS := "-s -w"
|
|||
endif
|
||||
KO_REGISTRY := ko.local
|
||||
KO_TAGS := $(GIT_SHA)
|
||||
KIND_IMAGE ?= kindest/node:v1.33.2
|
||||
KIND_IMAGE ?= kindest/node:v1.29.2
|
||||
|
||||
#########
|
||||
# TOOLS #
|
||||
|
@ -26,16 +29,17 @@ KIND_IMAGE ?= kindest/node:v1.33.2
|
|||
|
||||
TOOLS_DIR := $(PWD)/.tools
|
||||
CONTROLLER_GEN := $(TOOLS_DIR)/controller-gen
|
||||
CONTROLLER_GEN_VERSION := v0.15.0
|
||||
REGISTER_GEN := $(TOOLS_DIR)/register-gen
|
||||
DEEPCOPY_GEN := $(TOOLS_DIR)/deepcopy-gen
|
||||
CONVERSION_GEN := $(TOOLS_DIR)/conversion-gen
|
||||
CODE_GEN_VERSION := v0.33.3
|
||||
CODE_GEN_VERSION := v0.28.0
|
||||
REFERENCE_DOCS := $(TOOLS_DIR)/genref
|
||||
REFERENCE_DOCS_VERSION := latest
|
||||
KIND := $(TOOLS_DIR)/kind
|
||||
KIND_VERSION := v0.29.0
|
||||
KIND_VERSION := v0.22.0
|
||||
KO ?= $(TOOLS_DIR)/ko
|
||||
KO_VERSION ?= v0.18.0
|
||||
KO_VERSION ?= v0.15.1
|
||||
TOOLS := $(CONTROLLER_GEN) $(REGISTER_GEN) $(DEEPCOPY_GEN) $(CONVERSION_GEN) $(REFERENCE_DOCS) $(KIND) $(KO)
|
||||
PIP ?= "pip"
|
||||
ifeq ($(GOOS), darwin)
|
||||
|
@ -47,7 +51,7 @@ COMMA := ,
|
|||
|
||||
$(CONTROLLER_GEN):
|
||||
@echo Install controller-gen... >&2
|
||||
@cd ./hack/controller-gen && GOBIN=$(TOOLS_DIR) go install -buildvcs=false
|
||||
@GOBIN=$(TOOLS_DIR) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_GEN_VERSION)
|
||||
|
||||
$(REGISTER_GEN):
|
||||
@echo Install register-gen... >&2
|
||||
|
@ -86,32 +90,43 @@ clean-tools: ## Remove installed tools
|
|||
# CODEGEN #
|
||||
###########
|
||||
|
||||
$(GOPATH_SHIM):
|
||||
@echo Create gopath shim... >&2
|
||||
@mkdir -p $(GOPATH_SHIM)
|
||||
|
||||
.INTERMEDIATE: $(PACKAGE_SHIM)
|
||||
$(PACKAGE_SHIM): $(GOPATH_SHIM)
|
||||
@echo Create package shim... >&2
|
||||
@mkdir -p $(GOPATH_SHIM)/src/github.com/$(ORG) && ln -s -f ${PWD} $(PACKAGE_SHIM)
|
||||
|
||||
.PHONY: codegen-register
|
||||
codegen-register: ## Generate types registrations
|
||||
codegen-register: $(PACKAGE_SHIM)
|
||||
codegen-register: $(REGISTER_GEN)
|
||||
@echo Generate registration... >&2
|
||||
@$(REGISTER_GEN) \
|
||||
@GOPATH=$(GOPATH_SHIM) $(REGISTER_GEN) \
|
||||
--go-header-file=./hack/boilerplate.go.txt \
|
||||
--output-file zz_generated.register.go \
|
||||
./pkg/apis/...
|
||||
--input-dirs=$(INPUT_DIRS)
|
||||
|
||||
.PHONY: codegen-deepcopy
|
||||
codegen-deepcopy: ## Generate deep copy functions
|
||||
codegen-deepcopy: $(PACKAGE_SHIM)
|
||||
codegen-deepcopy: $(DEEPCOPY_GEN)
|
||||
@echo Generate deep copy functions... >&2
|
||||
@$(DEEPCOPY_GEN) \
|
||||
@GOPATH=$(GOPATH_SHIM) $(DEEPCOPY_GEN) \
|
||||
--go-header-file=./hack/boilerplate.go.txt \
|
||||
--output-file=zz_generated.deepcopy.go \
|
||||
./pkg/apis/...
|
||||
--input-dirs=$(INPUT_DIRS) \
|
||||
--output-file-base=zz_generated.deepcopy
|
||||
|
||||
.PHONY: codegen-conversion
|
||||
codegen-conversion: ## Generate conversion functions
|
||||
codegen-conversion: $(PACKAGE_SHIM)
|
||||
codegen-conversion: $(CONVERSION_GEN)
|
||||
@echo Generate conversion functions... >&2
|
||||
@$(CONVERSION_GEN) \
|
||||
@GOPATH=$(GOPATH_SHIM) $(CONVERSION_GEN) \
|
||||
--go-header-file=./hack/boilerplate.go.txt \
|
||||
--output-file=zz_generated.conversion.go \
|
||||
./pkg/apis/...
|
||||
--input-dirs=$(INPUT_DIRS) \
|
||||
--output-file-base=zz_generated.conversion
|
||||
|
||||
.PHONY: codegen-crds
|
||||
codegen-crds: ## Generate CRDs
|
||||
|
@ -120,8 +135,8 @@ codegen-crds: codegen-deepcopy
|
|||
codegen-crds: codegen-register
|
||||
codegen-crds: codegen-conversion
|
||||
@echo Generate crds... >&2
|
||||
@rm -rf $(CRDS_PATH)
|
||||
@$(CONTROLLER_GEN) paths=./pkg/apis/... crd:crdVersions=v1,ignoreUnexportedFields=true,generateEmbeddedObjectMeta=false output:dir=$(CRDS_PATH)
|
||||
@rm -rf $(CRDS_PATH)
|
||||
@go run ./hack/controller-gen -- paths=./pkg/apis/... crd:crdVersions=v1,ignoreUnexportedFields=true,generateEmbeddedObjectMeta=false output:dir=$(CRDS_PATH)
|
||||
@echo Copy generated CRDs to embed in the CLI... >&2
|
||||
@rm -rf pkg/data/crds && mkdir -p pkg/data/crds
|
||||
@cp $(CRDS_PATH)/* pkg/data/crds
|
||||
|
@ -130,7 +145,8 @@ codegen-crds: codegen-conversion
|
|||
codegen-cli-docs: ## Generate CLI docs
|
||||
codegen-cli-docs: build
|
||||
@echo Generate cli docs... >&2
|
||||
@rm -rf website/docs/reference/commands && mkdir -p website/docs/reference/commands
|
||||
@rm -rf website/docs/reference/commands && mkdir -p website/reference/docs/commands
|
||||
@rm -rf docs/user/commands && mkdir -p docs/user/commands
|
||||
@./$(CLI_BIN) docs -o website/docs/reference/commands --autogenTag=false
|
||||
|
||||
.PHONY: codegen-api-docs
|
||||
|
@ -146,7 +162,7 @@ codegen-api-docs: codegen-conversion
|
|||
.PHONY: codegen-jp-docs
|
||||
codegen-jp-docs: ## Generate JP docs
|
||||
@echo Generate jp docs... >&2
|
||||
@mkdir -p ./website/docs/reference/jp
|
||||
@rm -rf ./website/docs/reference/jp && mkdir -p ./website/docs/reference/jp
|
||||
@go run ./website/jp/main.go > ./website/docs/reference/jp/functions.md
|
||||
|
||||
.PHONY: codegen-mkdocs
|
||||
|
@ -183,8 +199,8 @@ codegen-schemas-json: codegen-schemas-openapi
|
|||
@$(PIP) install -r requirements.txt
|
||||
@rm -rf ./.temp/.schemas/json
|
||||
@rm -rf ./.schemas/json
|
||||
@openapi2jsonschema .temp/.schemas/openapi/v3/apis/chainsaw.kyverno.io/v1alpha1.json --kubernetes --strict --stand-alone --expanded -o ./.temp/.schemas/json
|
||||
@openapi2jsonschema .temp/.schemas/openapi/v3/apis/chainsaw.kyverno.io/v1alpha2.json --kubernetes --strict --stand-alone --expanded -o ./.temp/.schemas/json
|
||||
@openapi2jsonschema .temp/.schemas/openapi/v3/apis/chainsaw.kyverno.io/v1alpha1.json --kubernetes --stand-alone --expanded -o ./.temp/.schemas/json
|
||||
@openapi2jsonschema .temp/.schemas/openapi/v3/apis/chainsaw.kyverno.io/v1alpha2.json --kubernetes --stand-alone --expanded -o ./.temp/.schemas/json
|
||||
@mkdir -p ./.schemas/json
|
||||
@cp ./.temp/.schemas/json/configuration-chainsaw-*.json ./.schemas/json
|
||||
@cp ./.temp/.schemas/json/steptemplate-chainsaw-*.json ./.schemas/json
|
||||
|
@ -226,7 +242,7 @@ verify-codegen: codegen
|
|||
|
||||
.PHONY: mkdocs-serve
|
||||
mkdocs-serve: ## Generate and serve mkdocs website
|
||||
@echo Generate and serve mkdocs website... >&2
|
||||
@echo Generate and servemkdocs website... >&2
|
||||
@$(PIP) install -r requirements.txt
|
||||
@mkdocs serve -f ./website/mkdocs.yaml
|
||||
|
||||
|
@ -283,14 +299,7 @@ tests: $(CLI_BIN)
|
|||
e2e-tests: ## Run e2e tests
|
||||
e2e-tests: $(CLI_BIN)
|
||||
@echo Running e2e tests... >&2
|
||||
@./$(CLI_BIN) test ./testdata/e2e --remarshal --config ./testdata/e2e/config.yaml --values ./testdata/e2e/values.yaml
|
||||
|
||||
.PHONY: e2e-tests-no-cluster
|
||||
e2e-tests-no-cluster: ## Run e2e tests with --no-cluster
|
||||
e2e-tests-no-cluster: $(CLI_BIN)
|
||||
@echo Running e2e tests with --no-cluster... >&2
|
||||
@./$(CLI_BIN) test testdata/e2e/examples/script-env --no-cluster --remarshal --config ./testdata/e2e/config.yaml --values ./testdata/e2e/values.yaml
|
||||
@./$(CLI_BIN) test testdata/e2e/examples/dynamic-clusters --no-cluster --remarshal --config ./testdata/e2e/config.yaml --values ./testdata/e2e/values.yaml
|
||||
@./$(CLI_BIN) test --test-dir ./testdata/e2e --remarshal --config ./testdata/e2e/config.yaml --values ./testdata/e2e/values.yaml
|
||||
|
||||
.PHONY: e2e-tests-ko
|
||||
e2e-tests-ko: ## Run e2e tests from a docker container
|
||||
|
|
|
@ -51,7 +51,7 @@ To attend our community meetings, join the [Chainsaw group](https://groups.googl
|
|||
You will then be sent a meeting invite and will have access to the agenda and meeting notes.
|
||||
Any member may suggest topics for discussion.
|
||||
|
||||
This is a public, weekly meeting for Kyverno-Chainsaw maintainers to make announcements and provide project updates, and request input and feedback.
|
||||
This is a public, weekly for Kyverno-Chainsaw maintainers to make announcements and provide project updates, and request input and feedback.
|
||||
This forum allows community members to raise agenda items of any sort, including but not limited to any PRs or issues on which they are working.
|
||||
|
||||
Weekly every Thursday at 2:00 PM UTC
|
||||
|
|
38
chainsaw.rb
38
chainsaw.rb
|
@ -5,20 +5,20 @@
|
|||
class Chainsaw < Formula
|
||||
desc "Declarative Kubernetes end-to-end testing."
|
||||
homepage "https://kyverno.github.io/chainsaw"
|
||||
version "0.2.12"
|
||||
version "0.1.9"
|
||||
|
||||
on_macos do
|
||||
on_intel do
|
||||
url "https://github.com/kyverno/chainsaw/releases/download/v0.2.12/chainsaw_darwin_amd64.tar.gz"
|
||||
sha256 "b49dba1214b32024567b1edc7653498a644fbef18111bcc3e1c46dc52e1d194e"
|
||||
if Hardware::CPU.arm?
|
||||
url "https://github.com/kyverno/chainsaw/releases/download/v0.1.9/chainsaw_darwin_arm64.tar.gz"
|
||||
sha256 "4187956ba26fd5dadf6552bfa77e769afdac48c08e5741c46a8e38b07ca708bc"
|
||||
|
||||
def install
|
||||
bin.install "chainsaw"
|
||||
end
|
||||
end
|
||||
on_arm do
|
||||
url "https://github.com/kyverno/chainsaw/releases/download/v0.2.12/chainsaw_darwin_arm64.tar.gz"
|
||||
sha256 "717a07fcc4d781fff967b287880fed1d8b1e6af9fbecc7650a714c467f296d33"
|
||||
if Hardware::CPU.intel?
|
||||
url "https://github.com/kyverno/chainsaw/releases/download/v0.1.9/chainsaw_darwin_amd64.tar.gz"
|
||||
sha256 "8c65f3ee952aa04754d644f2ef3d5f489153638de4e71de6348d4628e5af0378"
|
||||
|
||||
def install
|
||||
bin.install "chainsaw"
|
||||
|
@ -27,24 +27,20 @@ class Chainsaw < Formula
|
|||
end
|
||||
|
||||
on_linux do
|
||||
on_intel do
|
||||
if Hardware::CPU.is_64_bit?
|
||||
url "https://github.com/kyverno/chainsaw/releases/download/v0.2.12/chainsaw_linux_amd64.tar.gz"
|
||||
sha256 "d6bfb17ba47af2db85edc0365288f92b5e1a4566f7ff130ec9b326f96856e209"
|
||||
if Hardware::CPU.intel?
|
||||
url "https://github.com/kyverno/chainsaw/releases/download/v0.1.9/chainsaw_linux_amd64.tar.gz"
|
||||
sha256 "4080d3bb5ea6de6f85198e413e24a5c7aee941f027ba8b545f7a1ddbaa2e2856"
|
||||
|
||||
def install
|
||||
bin.install "chainsaw"
|
||||
end
|
||||
def install
|
||||
bin.install "chainsaw"
|
||||
end
|
||||
end
|
||||
on_arm do
|
||||
if Hardware::CPU.is_64_bit?
|
||||
url "https://github.com/kyverno/chainsaw/releases/download/v0.2.12/chainsaw_linux_arm64.tar.gz"
|
||||
sha256 "72a6273d6da16a04e29e0fae232631b084852d21ddf25f88ed3d3de480125d30"
|
||||
if Hardware::CPU.arm? && Hardware::CPU.is_64_bit?
|
||||
url "https://github.com/kyverno/chainsaw/releases/download/v0.1.9/chainsaw_linux_arm64.tar.gz"
|
||||
sha256 "05f2cdce3f34989e71f47cd30e005a49fa8d7abefbede20311f96eed016a34b8"
|
||||
|
||||
def install
|
||||
bin.install "chainsaw"
|
||||
end
|
||||
def install
|
||||
bin.install "chainsaw"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
ignore:
|
||||
- 'hack/**/*.go'
|
||||
- 'website/**/*.go'
|
||||
- 'pkg/apis/**/zz_*.go'
|
||||
- 'pkg/testing/*.go'
|
||||
- '**/*_test.go'
|
||||
- ^pkg/apis/v1alpha1/zz_generated\.deepcopy\.go$
|
||||
- ^pkg/apis/v1alpha1/zz_generated\.register\.go$
|
||||
- ^pkg/testing/.*\.go$
|
||||
- ^.*_test\.go$
|
||||
|
|
184
go.mod
184
go.mod
|
@ -1,105 +1,98 @@
|
|||
module github.com/kyverno/chainsaw
|
||||
|
||||
go 1.24.2
|
||||
go 1.22.2
|
||||
|
||||
require (
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible
|
||||
github.com/dustinkirkland/golang-petname v0.0.0-20240428194347-eebcea082ee0
|
||||
github.com/evanphx/json-patch v5.9.11+incompatible
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/go-logr/logr v1.4.3
|
||||
github.com/google/cel-go v0.23.2
|
||||
github.com/fatih/color v1.17.0
|
||||
github.com/go-logr/logr v1.4.2
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/hashicorp/go-getter v1.7.8
|
||||
github.com/jmespath-community/go-jmespath v1.1.2-0.20240930152130-6eb5a346873f
|
||||
github.com/jstemmer/go-junit-report/v2 v2.1.0
|
||||
github.com/kudobuilder/kuttl v0.20.0
|
||||
github.com/kyverno/kyverno-json v0.0.4-0.20241008103124-b294ee72a2bf
|
||||
github.com/hashicorp/go-getter v1.7.5
|
||||
github.com/jmespath-community/go-jmespath v1.1.2-0.20240627155901-bdbb290f571e
|
||||
github.com/kudobuilder/kuttl v0.18.0
|
||||
github.com/kyverno/kyverno-json v0.0.3
|
||||
github.com/kyverno/pkg/ext v0.0.0-20240418121121-df8add26c55c
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
|
||||
github.com/prometheus/common v0.65.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/pflag v1.0.7
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/prometheus/common v0.47.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
golang.org/x/exp v0.0.0-20240707233637-46b078467d37
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.33.3
|
||||
k8s.io/apimachinery v0.33.3
|
||||
k8s.io/apiserver v0.33.3
|
||||
k8s.io/client-go v0.33.3
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
|
||||
sigs.k8s.io/controller-runtime v0.21.0
|
||||
sigs.k8s.io/kubectl-validate v0.0.5-0.20241223122011-eb064d2f92d5
|
||||
sigs.k8s.io/yaml v1.6.0
|
||||
k8s.io/api v0.30.3
|
||||
k8s.io/apiextensions-apiserver v0.30.3
|
||||
k8s.io/apimachinery v0.30.3
|
||||
k8s.io/client-go v0.30.3
|
||||
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0
|
||||
sigs.k8s.io/controller-runtime v0.18.4
|
||||
sigs.k8s.io/controller-tools v0.15.0
|
||||
sigs.k8s.io/kubectl-validate v0.0.4
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.19.1 // indirect
|
||||
cloud.google.com/go v0.115.1 // indirect
|
||||
cloud.google.com/go/auth v0.9.7 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.2 // indirect
|
||||
cloud.google.com/go/iam v1.2.1 // indirect
|
||||
cloud.google.com/go/monitoring v1.21.1 // indirect
|
||||
cloud.google.com/go/storage v1.44.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect
|
||||
cloud.google.com/go v0.115.0 // indirect
|
||||
cloud.google.com/go/auth v0.7.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.4.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.10 // indirect
|
||||
cloud.google.com/go/storage v1.43.0 // indirect
|
||||
github.com/IGLOU-EU/go-wildcard v1.0.3 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/aquilax/truncate v1.0.1 // indirect
|
||||
github.com/aws/aws-sdk-go v1.55.6 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
|
||||
github.com/aquilax/truncate v1.0.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go v1.54.17 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.32.3 // indirect
|
||||
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
|
||||
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/gobuffalo/flect v1.0.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/gnostic-models v0.6.9 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/google/cel-go v0.17.8 // indirect
|
||||
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.5 // indirect
|
||||
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/huandu/xstrings v1.5.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jinzhu/copier v0.4.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
|
@ -111,59 +104,52 @@ require (
|
|||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/prometheus/client_golang v1.22.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/prometheus/client_golang v1.18.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.21 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.21 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.14 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.14 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.29.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
|
||||
go.opentelemetry.io/otel v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||
go.opentelemetry.io/otel v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/crypto v0.38.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
google.golang.org/api v0.199.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20241007155032-5fefd90f89a9 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
|
||||
google.golang.org/grpc v1.68.1 // indirect
|
||||
google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
golang.org/x/crypto v0.25.0 // indirect
|
||||
golang.org/x/mod v0.19.0 // indirect
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/oauth2 v0.21.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/term v0.22.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.23.0 // indirect
|
||||
google.golang.org/api v0.188.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240709173604-40e1e62336c5 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240709173604-40e1e62336c5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 // indirect
|
||||
google.golang.org/grpc v1.65.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.33.0 // indirect
|
||||
k8s.io/component-base v0.33.3 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
k8s.io/apiserver v0.30.3 // indirect
|
||||
k8s.io/component-base v0.30.3 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
)
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
module github.com/kyverno/chainsaw/hack/controller-gen
|
||||
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/spf13/cobra v1.9.1
|
||||
k8s.io/apiextensions-apiserver v0.33.3
|
||||
sigs.k8s.io/controller-tools v0.17.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/gobuffalo/flect v1.0.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
golang.org/x/tools v0.31.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
k8s.io/apimachinery v0.33.3 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
|
@ -1,135 +0,0 @@
|
|||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
|
||||
github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
|
||||
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs=
|
||||
k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8=
|
||||
k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
|
||||
k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-tools v0.17.2 h1:jNFOKps8WnaRKZU2R+4vRCHnXyJanVmXBWqkuUPFyFg=
|
||||
sigs.k8s.io/controller-tools v0.17.2/go.mod h1:4q5tZG2JniS5M5bkiXY2/potOiXyhoZVw/U48vLkXk0=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
|
@ -1,45 +0,0 @@
|
|||
package apis
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
gocel "github.com/google/cel-go/cel"
|
||||
"github.com/jmespath-community/go-jmespath/pkg/binding"
|
||||
"github.com/kyverno/chainsaw/pkg/engine/functions"
|
||||
"github.com/kyverno/kyverno-json/pkg/core/compilers"
|
||||
"github.com/kyverno/kyverno-json/pkg/core/compilers/cel"
|
||||
"github.com/kyverno/kyverno-json/pkg/core/compilers/jp"
|
||||
"k8s.io/apiserver/pkg/cel/library"
|
||||
)
|
||||
|
||||
var (
|
||||
env = sync.OnceValues(func() (*gocel.Env, error) {
|
||||
env, err := cel.DefaultEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return env.Extend(
|
||||
library.URLs(),
|
||||
library.Regex(),
|
||||
library.Lists(),
|
||||
library.Authz(),
|
||||
library.Quantity(),
|
||||
library.IP(),
|
||||
library.CIDR(),
|
||||
library.Format(),
|
||||
library.AuthzSelectors(),
|
||||
)
|
||||
})
|
||||
defaultCompilers = compilers.Compilers{
|
||||
Jp: jp.NewCompiler(jp.WithFunctionCaller(functions.Caller())),
|
||||
Cel: cel.NewCompiler(env),
|
||||
}
|
||||
DefaultCompilers = defaultCompilers.WithDefaultCompiler(compilers.CompilerJP)
|
||||
)
|
||||
|
||||
type Bindings = binding.Bindings
|
||||
|
||||
var (
|
||||
NewBinding = binding.NewBinding
|
||||
NewBindings = binding.NewBindings
|
||||
)
|
|
@ -22,14 +22,12 @@ func Convert_v1alpha2_ConfigurationSpec_To_v1alpha1_ConfigurationSpec(in *v1alph
|
|||
out.ForceTerminationGracePeriod = in.Execution.ForceTerminationGracePeriod
|
||||
out.Namespace = in.Namespace.Name
|
||||
out.NamespaceTemplate = in.Namespace.Template
|
||||
out.NamespaceTemplateCompiler = in.Namespace.Compiler
|
||||
if in := in.Report; in != nil {
|
||||
out.ReportFormat = v1alpha1.ReportFormatType(in.Format)
|
||||
out.ReportPath = in.Path
|
||||
out.ReportName = in.Name
|
||||
}
|
||||
out.Template = in.Templating.Enabled
|
||||
out.Compiler = in.Templating.Compiler
|
||||
out.Template = &in.Templating.Enabled
|
||||
out.Timeouts = in.Timeouts
|
||||
return nil
|
||||
}
|
||||
|
@ -60,7 +58,6 @@ func Convert_v1alpha1_ConfigurationSpec_To_v1alpha2_ConfigurationSpec(in *v1alph
|
|||
}
|
||||
out.Namespace = v1alpha2.NamespaceOptions{
|
||||
Name: in.Namespace,
|
||||
Compiler: in.NamespaceTemplateCompiler,
|
||||
Template: in.NamespaceTemplate,
|
||||
}
|
||||
out.Report = &v1alpha2.ReportOptions{
|
||||
|
@ -68,9 +65,14 @@ func Convert_v1alpha1_ConfigurationSpec_To_v1alpha2_ConfigurationSpec(in *v1alph
|
|||
Path: in.ReportPath,
|
||||
Name: in.ReportName,
|
||||
}
|
||||
out.Templating = v1alpha2.TemplatingOptions{
|
||||
Enabled: in.Template,
|
||||
Compiler: in.Compiler,
|
||||
if in.Template == nil {
|
||||
out.Templating = v1alpha2.TemplatingOptions{
|
||||
Enabled: true,
|
||||
}
|
||||
} else {
|
||||
out.Templating = v1alpha2.TemplatingOptions{
|
||||
Enabled: *in.Template,
|
||||
}
|
||||
}
|
||||
out.Timeouts = in.Timeouts
|
||||
return nil
|
||||
|
|
|
@ -26,7 +26,7 @@ type ActionCheckRef struct {
|
|||
|
||||
// Check provides a check used in assertions.
|
||||
// +optional
|
||||
Check *Projection `json:"resource,omitempty"`
|
||||
Check *Check `json:"resource,omitempty"`
|
||||
|
||||
// Template determines whether resources should be considered for templating.
|
||||
// +optional
|
||||
|
@ -35,9 +35,9 @@ type ActionCheckRef struct {
|
|||
|
||||
// ActionClusters contains clusters options for an action.
|
||||
type ActionClusters struct {
|
||||
// Cluster defines the target cluster (will be inherited if not specified).
|
||||
// Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).
|
||||
// +optional
|
||||
Cluster *string `json:"cluster,omitempty"`
|
||||
Cluster string `json:"cluster,omitempty"`
|
||||
|
||||
// Clusters holds a registry to clusters to support multi-cluster tests.
|
||||
// +optional
|
||||
|
@ -60,10 +60,6 @@ type ActionEnv struct {
|
|||
// SkipLogOutput removes the output from the command. Useful for sensitive logs or to reduce noise.
|
||||
// +optional
|
||||
SkipLogOutput bool `json:"skipLogOutput,omitempty"`
|
||||
|
||||
// SkipCommandOutput removes the command from the output logs.
|
||||
// +optional
|
||||
SkipCommandOutput bool `json:"skipCommandOutput,omitempty"`
|
||||
}
|
||||
|
||||
// ActionExpectations contains expectations for an action.
|
||||
|
@ -101,7 +97,7 @@ type ActionObjectSelector struct {
|
|||
|
||||
// Selector defines labels selector.
|
||||
// +optional
|
||||
Selector Expression `json:"selector,omitempty"`
|
||||
Selector string `json:"selector,omitempty"`
|
||||
}
|
||||
|
||||
// ActionOutputs contains outputs options for an action.
|
||||
|
@ -116,7 +112,7 @@ type FileRef struct {
|
|||
// File is the path to the referenced file. This can be a direct path to a file
|
||||
// or an expression that matches multiple files, such as "manifest/*.yaml" for all YAML
|
||||
// files within the "manifest" directory.
|
||||
File Expression `json:"file,omitempty"`
|
||||
File string `json:"file,omitempty"`
|
||||
}
|
||||
|
||||
// ActionResourceRef contains resource reference options for an action.
|
||||
|
@ -178,10 +174,6 @@ type Command struct {
|
|||
// Args is the command arguments.
|
||||
// +optional
|
||||
Args []string `json:"args,omitempty"`
|
||||
|
||||
// WorkDir is the working directory for command.
|
||||
// +optional
|
||||
WorkDir *string `json:"workDir,omitempty"`
|
||||
}
|
||||
|
||||
// Create represents a set of resources that should be created.
|
||||
|
@ -212,7 +204,7 @@ type Delete struct {
|
|||
// or an expression that matches multiple files, such as "manifest/*.yaml" for all YAML
|
||||
// files within the "manifest" directory.
|
||||
// +optional
|
||||
File Expression `json:"file,omitempty"`
|
||||
File string `json:"file,omitempty"`
|
||||
|
||||
// Ref determines objects to be deleted.
|
||||
// +optional
|
||||
|
@ -282,7 +274,7 @@ type PodLogs struct {
|
|||
|
||||
// Container in pod to get logs from else --all-containers is used.
|
||||
// +optional
|
||||
Container Expression `json:"container,omitempty"`
|
||||
Container string `json:"container,omitempty"`
|
||||
|
||||
// Tail is the number of last lines to collect from pods. If omitted or zero,
|
||||
// then the default is 10 if you use a selector, or -1 (all) if you use a pod name.
|
||||
|
@ -301,11 +293,11 @@ type Proxy struct {
|
|||
|
||||
// TargetPort defines the target port to proxy the request.
|
||||
// +optional
|
||||
TargetPort Expression `json:"port,omitempty"`
|
||||
TargetPort string `json:"port,omitempty"`
|
||||
|
||||
// TargetPath defines the target path to proxy the request.
|
||||
// +optional
|
||||
TargetPath Expression `json:"path,omitempty"`
|
||||
TargetPath string `json:"path,omitempty"`
|
||||
}
|
||||
|
||||
// Script describes a script to run as a part of a test step.
|
||||
|
@ -320,10 +312,6 @@ type Script struct {
|
|||
// Content defines a shell script (run with "sh -c ...").
|
||||
// +optional
|
||||
Content string `json:"content,omitempty"`
|
||||
|
||||
// WorkDir is the working directory for script.
|
||||
// +optional
|
||||
WorkDir *string `json:"workDir,omitempty"`
|
||||
}
|
||||
|
||||
// Sleep represents a duration while nothing happens.
|
||||
|
@ -373,11 +361,11 @@ type WaitFor struct {
|
|||
// WaitForCondition represents parameters for waiting on a specific condition of a resource.
|
||||
type WaitForCondition struct {
|
||||
// Name defines the specific condition to wait for, e.g., "Available", "Ready".
|
||||
Name Expression `json:"name"`
|
||||
Name string `json:"name"`
|
||||
|
||||
// Value defines the specific condition status to wait for, e.g., "True", "False".
|
||||
// +optional
|
||||
Value *Expression `json:"value,omitempty"`
|
||||
Value *string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
// WaitForDeletion represents parameters for waiting on a resource's deletion.
|
||||
|
@ -386,9 +374,8 @@ type WaitForDeletion struct{}
|
|||
// WaitForJsonPath represents parameters for waiting on a json path of a resource.
|
||||
type WaitForJsonPath struct {
|
||||
// Path defines the json path to wait for, e.g. '{.status.phase}'.
|
||||
Path Expression `json:"path"`
|
||||
Path string `json:"path"`
|
||||
|
||||
// Value defines the expected value to wait for, e.g., "Running".
|
||||
// +optional
|
||||
Value *Expression `json:"value,omitempty"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
|
|
@ -15,10 +15,6 @@ type CatchFinally struct {
|
|||
// +optional
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Compiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
Compiler *Compiler `json:"compiler,omitempty"`
|
||||
|
||||
// PodLogs determines the pod logs collector to execute.
|
||||
// +optional
|
||||
PodLogs *PodLogs `json:"podLogs,omitempty"`
|
||||
|
|
|
@ -25,14 +25,14 @@ func TestFinally_Bindings(t *testing.T) {
|
|||
}{{
|
||||
fields: fields{
|
||||
Command: &Command{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
fields: fields{
|
||||
Delete: &Delete{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
|
@ -55,7 +55,7 @@ func TestFinally_Bindings(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
Script: &Script{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
|
@ -107,7 +107,7 @@ func TestFinally_Outputs(t *testing.T) {
|
|||
}{{
|
||||
fields: fields{
|
||||
Command: &Command{
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{Name: "foo", Value: NewProjection("bar")}}}},
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{"foo", Any{Value: "bar"}}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
|
@ -134,7 +134,7 @@ func TestFinally_Outputs(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
Script: &Script{
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{Name: "foo", Value: NewProjection("bar")}}}},
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{"foo", Any{Value: "bar"}}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
|
|
|
@ -25,8 +25,7 @@ type Configuration struct {
|
|||
type ConfigurationSpec struct {
|
||||
// Global timeouts configuration. Applies to all tests/test steps if not overridden.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
Timeouts DefaultTimeouts `json:"timeouts"`
|
||||
Timeouts Timeouts `json:"timeouts"`
|
||||
|
||||
// If set, do not delete the resources after running the tests (implies SkipClusterDelete).
|
||||
// +optional
|
||||
|
@ -34,12 +33,7 @@ type ConfigurationSpec struct {
|
|||
|
||||
// Template determines whether resources should be considered for templating.
|
||||
// +optional
|
||||
// +kubebuilder:default:=true
|
||||
Template bool `json:"template"`
|
||||
|
||||
// Compiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
Compiler *Compiler `json:"compiler,omitempty"`
|
||||
Template *bool `json:"template,omitempty"`
|
||||
|
||||
// FailFast determines whether the test should stop upon encountering the first failure.
|
||||
// +optional
|
||||
|
@ -58,10 +52,10 @@ type ConfigurationSpec struct {
|
|||
// +kubebuilder:default:=Background
|
||||
DeletionPropagationPolicy metav1.DeletionPropagation `json:"deletionPropagationPolicy,omitempty"`
|
||||
|
||||
// ReportFormat determines test report format (JSON, XML, JUNIT-TEST, JUNIT-STEP, JUNIT-OPERATION, nil) nil == no report.
|
||||
// ReportFormat determines test report format (JSON|XML|nil) nil == no report.
|
||||
// maps to report.Type, however we don't want generated.deepcopy to have reference to it.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Enum:=JSON;XML;JUNIT-TEST;JUNIT-STEP;JUNIT-OPERATION;
|
||||
// +kubebuilder:validation:Enum:=JSON;XML;
|
||||
ReportFormat ReportFormatType `json:"reportFormat,omitempty"`
|
||||
|
||||
// ReportPath defines the path.
|
||||
|
@ -79,13 +73,9 @@ type ConfigurationSpec struct {
|
|||
// +optional
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
|
||||
// NamespaceTemplateCompiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
NamespaceTemplateCompiler *Compiler `json:"namespaceTemplateCompiler,omitempty"`
|
||||
|
||||
// NamespaceTemplate defines a template to create the test namespace.
|
||||
// +optional
|
||||
NamespaceTemplate *Projection `json:"namespaceTemplate,omitempty"`
|
||||
NamespaceTemplate *Any `json:"namespaceTemplate,omitempty"`
|
||||
|
||||
// FullName makes use of the full test case folder path instead of the folder name.
|
||||
// +optional
|
||||
|
@ -132,10 +122,7 @@ type ConfigurationSpec struct {
|
|||
type ReportFormatType string
|
||||
|
||||
const (
|
||||
JSONFormat ReportFormatType = "JSON"
|
||||
XMLFormat ReportFormatType = "XML"
|
||||
JUnitTestFormat ReportFormatType = "JUNIT-TEST"
|
||||
JUnitStepFormat ReportFormatType = "JUNIT-STEP"
|
||||
JUnitOperationFormat ReportFormatType = "JUNIT-OPERATION"
|
||||
NoReport ReportFormatType = ""
|
||||
JSONFormat ReportFormatType = "JSON"
|
||||
XMLFormat ReportFormatType = "XML"
|
||||
NoReport ReportFormatType = ""
|
||||
)
|
||||
|
|
|
@ -10,10 +10,6 @@ type OperationBase struct {
|
|||
// Even if the test continues executing, it will still be reported as failed.
|
||||
// +optional
|
||||
ContinueOnError *bool `json:"continueOnError,omitempty"`
|
||||
|
||||
// Compiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
Compiler *Compiler `json:"compiler,omitempty"`
|
||||
}
|
||||
|
||||
// Operation defines a single operation, only one action is permitted for a given operation.
|
||||
|
|
|
@ -7,110 +7,111 @@ import (
|
|||
)
|
||||
|
||||
func TestOperation_Bindings(t *testing.T) {
|
||||
type fields struct {
|
||||
Apply *Apply
|
||||
Assert *Assert
|
||||
Command *Command
|
||||
Create *Create
|
||||
Delete *Delete
|
||||
Error *Error
|
||||
Patch *Patch
|
||||
Script *Script
|
||||
Sleep *Sleep
|
||||
Update *Update
|
||||
Wait *Wait
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
operation Operation
|
||||
want int
|
||||
name string
|
||||
fields fields
|
||||
want int
|
||||
}{{
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Apply: &Apply{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Assert: &Assert{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Command: &Command{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Create: &Create{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Delete: &Delete{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
Describe: &Describe{},
|
||||
},
|
||||
want: 0,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Error: &Error{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
Events: &Events{},
|
||||
},
|
||||
want: 0,
|
||||
}, {
|
||||
operation: Operation{
|
||||
Get: &Get{},
|
||||
},
|
||||
want: 0,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Patch: &Patch{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
PodLogs: &PodLogs{},
|
||||
},
|
||||
want: 0,
|
||||
}, {
|
||||
operation: Operation{
|
||||
Proxy: &Proxy{},
|
||||
},
|
||||
want: 0,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Script: &Script{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Sleep: &Sleep{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Update: &Update{
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{Name: "foo", Value: NewProjection("bar")}}},
|
||||
ActionBindings: ActionBindings{Bindings: []Binding{{"foo", Any{Value: "bar"}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Wait: &Wait{},
|
||||
},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := tt.operation.Bindings()
|
||||
c := &Operation{
|
||||
Apply: tt.fields.Apply,
|
||||
Assert: tt.fields.Assert,
|
||||
Command: tt.fields.Command,
|
||||
Create: tt.fields.Create,
|
||||
Delete: tt.fields.Delete,
|
||||
Error: tt.fields.Error,
|
||||
Patch: tt.fields.Patch,
|
||||
Script: tt.fields.Script,
|
||||
Sleep: tt.fields.Sleep,
|
||||
Update: tt.fields.Update,
|
||||
Wait: tt.fields.Wait,
|
||||
}
|
||||
got := c.Bindings()
|
||||
assert.Equal(t, tt.want, len(got))
|
||||
})
|
||||
}
|
||||
|
@ -118,96 +119,102 @@ func TestOperation_Bindings(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestOperation_Outputs(t *testing.T) {
|
||||
type fields struct {
|
||||
Apply *Apply
|
||||
Assert *Assert
|
||||
Command *Command
|
||||
Create *Create
|
||||
Delete *Delete
|
||||
Error *Error
|
||||
Patch *Patch
|
||||
Script *Script
|
||||
Sleep *Sleep
|
||||
Update *Update
|
||||
Wait *Wait
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
operation Operation
|
||||
want int
|
||||
name string
|
||||
fields fields
|
||||
want int
|
||||
}{{
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Apply: &Apply{
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{Name: "foo", Value: NewProjection("bar")}}}},
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{"foo", Any{Value: "bar"}}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Assert: &Assert{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Command: &Command{
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{Name: "foo", Value: NewProjection("bar")}}}},
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{"foo", Any{Value: "bar"}}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Create: &Create{
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{Name: "foo", Value: NewProjection("bar")}}}},
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{"foo", Any{Value: "bar"}}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Delete: &Delete{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
Describe: &Describe{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Error: &Error{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
Events: &Events{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
Get: &Get{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Patch: &Patch{
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{Name: "foo", Value: NewProjection("bar")}}}},
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{"foo", Any{Value: "bar"}}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
PodLogs: &PodLogs{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
Proxy: &Proxy{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Script: &Script{
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{Name: "foo", Value: NewProjection("bar")}}}},
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{"foo", Any{Value: "bar"}}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Sleep: &Sleep{},
|
||||
},
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Update: &Update{
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{Name: "foo", Value: NewProjection("bar")}}}},
|
||||
ActionOutputs: ActionOutputs{Outputs: []Output{{Binding: Binding{"foo", Any{Value: "bar"}}}}},
|
||||
},
|
||||
},
|
||||
want: 1,
|
||||
}, {
|
||||
operation: Operation{
|
||||
fields: fields{
|
||||
Wait: &Wait{},
|
||||
},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := tt.operation.Outputs()
|
||||
c := &Operation{
|
||||
Apply: tt.fields.Apply,
|
||||
Assert: tt.fields.Assert,
|
||||
Command: tt.fields.Command,
|
||||
Create: tt.fields.Create,
|
||||
Delete: tt.fields.Delete,
|
||||
Error: tt.fields.Error,
|
||||
Patch: tt.fields.Patch,
|
||||
Script: tt.fields.Script,
|
||||
Sleep: tt.fields.Sleep,
|
||||
Update: tt.fields.Update,
|
||||
Wait: tt.fields.Wait,
|
||||
}
|
||||
got := c.Outputs()
|
||||
assert.Equal(t, tt.want, len(got))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/kyverno/kyverno-json/pkg/utils/copy"
|
||||
)
|
||||
|
||||
// Projection can be any type.
|
||||
// +k8s:deepcopy-gen=false
|
||||
// +kubebuilder:validation:XPreserveUnknownFields
|
||||
// +kubebuilder:validation:Type:=""
|
||||
type Projection struct {
|
||||
_value any
|
||||
}
|
||||
|
||||
func NewProjection(value any) Projection {
|
||||
return Projection{
|
||||
_value: value,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Projection) Value() any {
|
||||
return a._value
|
||||
}
|
||||
|
||||
func (a *Projection) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(a._value)
|
||||
}
|
||||
|
||||
func (a *Projection) UnmarshalJSON(data []byte) error {
|
||||
var v any
|
||||
err := json.Unmarshal(data, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a._value = v
|
||||
return nil
|
||||
}
|
||||
|
||||
func (in *Projection) DeepCopyInto(out *Projection) {
|
||||
out._value = copy.DeepCopy(in._value)
|
||||
}
|
||||
|
||||
func (in *Projection) DeepCopy() *Projection {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Projection)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
|
@ -46,37 +46,19 @@ type StepTemplateSpec struct {
|
|||
}
|
||||
|
||||
// TestStep contains the test step definition used in a test spec.
|
||||
// +kubebuilder:not:={required:{use},anyOf:{{required:{try}},{required:{catch}},{required:{finally}},{required:{cleanup}}}}
|
||||
// +kubebuilder:not:={required:{from},anyOf:{{required:{try}},{required:{catch}},{required:{finally}},{required:{cleanup}}}}
|
||||
type TestStep struct {
|
||||
// Name of the step.
|
||||
// +optional
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Use defines a reference to a step template.
|
||||
Use *Use `json:"use,omitempty"`
|
||||
// From references a step template.
|
||||
From string `json:"from,omitempty"`
|
||||
|
||||
// TestStepSpec of the step.
|
||||
TestStepSpec `json:",inline"`
|
||||
}
|
||||
|
||||
// Use defines a reference to a step template.
|
||||
type Use struct {
|
||||
// Template references a step template.
|
||||
Template string `json:"template"`
|
||||
|
||||
// With defines arguments passed to the step template.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
With With `json:"with"`
|
||||
}
|
||||
|
||||
// With defines arguments passed to step templates.
|
||||
type With struct {
|
||||
// Bindings defines additional binding key/values.
|
||||
// +optional
|
||||
Bindings []Binding `json:"bindings,omitempty"`
|
||||
}
|
||||
|
||||
// TestStepSpec defines the desired state and behavior for each test step.
|
||||
type TestStepSpec struct {
|
||||
// Description contains a description of the test step.
|
||||
|
@ -94,9 +76,9 @@ type TestStepSpec struct {
|
|||
// +kubebuilder:validation:Enum:=Orphan;Background;Foreground
|
||||
DeletionPropagationPolicy *metav1.DeletionPropagation `json:"deletionPropagationPolicy,omitempty"`
|
||||
|
||||
// Cluster defines the target cluster (will be inherited if not specified).
|
||||
// Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).
|
||||
// +optional
|
||||
Cluster *string `json:"cluster,omitempty"`
|
||||
Cluster string `json:"cluster,omitempty"`
|
||||
|
||||
// Clusters holds a registry to clusters to support multi-cluster tests.
|
||||
// +optional
|
||||
|
@ -110,10 +92,6 @@ type TestStepSpec struct {
|
|||
// +optional
|
||||
Template *bool `json:"template,omitempty"`
|
||||
|
||||
// Compiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
Compiler *Compiler `json:"compiler,omitempty"`
|
||||
|
||||
// Bindings defines additional binding key/values.
|
||||
// +optional
|
||||
Bindings []Binding `json:"bindings,omitempty"`
|
||||
|
|
|
@ -28,17 +28,13 @@ type TestSpec struct {
|
|||
// +optional
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// FailFast determines whether the test should stop upon encountering the first failure.
|
||||
// +optional
|
||||
FailFast *bool `json:"failFast,omitempty"`
|
||||
|
||||
// Timeouts for the test. Overrides the global timeouts set in the Configuration on a per operation basis.
|
||||
// +optional
|
||||
Timeouts *Timeouts `json:"timeouts,omitempty"`
|
||||
|
||||
// Cluster defines the target cluster (will be inherited if not specified).
|
||||
// Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).
|
||||
// +optional
|
||||
Cluster *string `json:"cluster,omitempty"`
|
||||
Cluster string `json:"cluster,omitempty"`
|
||||
|
||||
// Clusters holds a registry to clusters to support multi-cluster tests.
|
||||
// +optional
|
||||
|
@ -60,21 +56,13 @@ type TestSpec struct {
|
|||
// +optional
|
||||
Template *bool `json:"template,omitempty"`
|
||||
|
||||
// Compiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
Compiler *Compiler `json:"compiler,omitempty"`
|
||||
|
||||
// Namespace determines whether the test should run in a random ephemeral namespace or not.
|
||||
// +optional
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
|
||||
// NamespaceTemplate defines a template to create the test namespace.
|
||||
// +optional
|
||||
NamespaceTemplate *Projection `json:"namespaceTemplate,omitempty"`
|
||||
|
||||
// NamespaceTemplateCompiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
NamespaceTemplateCompiler *Compiler `json:"namespaceTemplateCompiler,omitempty"`
|
||||
NamespaceTemplate *Any `json:"namespaceTemplate,omitempty"`
|
||||
|
||||
// Scenarios defines test scenarios.
|
||||
// +optional
|
||||
|
|
|
@ -1,57 +1,40 @@
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/jmespath-community/go-jmespath/pkg/parsing"
|
||||
"github.com/kyverno/chainsaw/pkg/apis"
|
||||
"github.com/kyverno/chainsaw/pkg/expressions"
|
||||
"github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
|
||||
"github.com/kyverno/kyverno-json/pkg/core/compilers"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
EngineJP = v1alpha1.EngineJP
|
||||
EngineCEL = v1alpha1.EngineCEL
|
||||
)
|
||||
var identifier = regexp.MustCompile(`^(?:\w+|\(.+\))$`)
|
||||
|
||||
var (
|
||||
identifier = regexp.MustCompile(`^(?:\w+|\(.+\))$`)
|
||||
NewAny = v1alpha1.NewAny
|
||||
NewCheck = v1alpha1.NewAssertionTree
|
||||
NewMatch = v1alpha1.NewAssertionTree
|
||||
)
|
||||
|
||||
type Compiler = v1alpha1.Compiler
|
||||
// Any represents any type.
|
||||
type Any = v1alpha1.Any
|
||||
|
||||
// Binding represents a key/value set as a binding in an executing test.
|
||||
type Binding struct {
|
||||
// Name the name of the binding.
|
||||
// +kubebuilder:validation:Type:=string
|
||||
// +kubebuilder:validation:Pattern:=`^(?:\w+|\(.+\))$`
|
||||
Name Expression `json:"name"`
|
||||
|
||||
// Compiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
Compiler *Compiler `json:"compiler,omitempty"`
|
||||
// +kubebuilder:validation:Pattern=`^(?:\w+|\(.+\))$`
|
||||
Name string `json:"name"`
|
||||
|
||||
// Value value of the binding.
|
||||
Value Projection `json:"value"`
|
||||
// +kubebuilder:validation:Schemaless
|
||||
// +kubebuilder:pruning:PreserveUnknownFields
|
||||
Value Any `json:"value"`
|
||||
}
|
||||
|
||||
func (b Binding) CheckName() error {
|
||||
if !identifier.MatchString(string(b.Name)) {
|
||||
if !identifier.MatchString(b.Name) {
|
||||
return fmt.Errorf("invalid name %s", b.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check represents a check to be applied on the result of an operation.
|
||||
type Check = v1alpha1.AssertionTree
|
||||
type Check = Any
|
||||
|
||||
// Cluster defines cluster config and context.
|
||||
type Cluster struct {
|
||||
|
@ -77,60 +60,24 @@ type Expectation struct {
|
|||
Check Check `json:"check"`
|
||||
}
|
||||
|
||||
// Expression defines an expression to be used in string fields.
|
||||
type Expression string
|
||||
|
||||
func (e *Expression) MarshalJSON() ([]byte, error) {
|
||||
if e == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return json.Marshal(string(*e))
|
||||
}
|
||||
|
||||
func (e *Expression) UnmarshalJSON(data []byte) error {
|
||||
var statement string
|
||||
err := json.Unmarshal(data, &statement)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = Expression(statement)
|
||||
expression := expressions.Parse(context.TODO(), statement)
|
||||
if expression == nil {
|
||||
return nil
|
||||
}
|
||||
if expression.Engine == "" {
|
||||
return nil
|
||||
}
|
||||
parser := parsing.NewParser()
|
||||
if _, err := parser.Parse(statement); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e Expression) Value(ctx context.Context, compilers compilers.Compilers, bindings apis.Bindings) (string, error) {
|
||||
return expressions.String(ctx, compilers, string(e), bindings)
|
||||
}
|
||||
|
||||
// Format determines the output format (json or yaml).
|
||||
// +kubebuilder:validation:Type:=string
|
||||
// +kubebuilder:validation:Pattern:=`^(?:json|yaml|\(.+\))$`
|
||||
type Format Expression
|
||||
// +kubebuilder:validation:Pattern=`^(?:json|yaml|\(.+\))$`
|
||||
type Format string
|
||||
|
||||
// Match represents a match condition against an evaluated object.
|
||||
type Match = v1alpha1.AssertionTree
|
||||
type Match = Any
|
||||
|
||||
// ObjectName represents an object namespace and name.
|
||||
type ObjectName struct {
|
||||
// Namespace of the referent.
|
||||
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
|
||||
// +optional
|
||||
Namespace Expression `json:"namespace,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
|
||||
// Name of the referent.
|
||||
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
// +optional
|
||||
Name Expression `json:"name,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
// ObjectReference represents one or more objects with a specific apiVersion and kind.
|
||||
|
@ -148,11 +95,11 @@ type ObjectReference struct {
|
|||
// ObjectType represents a specific apiVersion and kind.
|
||||
type ObjectType struct {
|
||||
// API version of the referent.
|
||||
APIVersion Expression `json:"apiVersion"`
|
||||
APIVersion string `json:"apiVersion"`
|
||||
|
||||
// Kind of the referent.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
Kind Expression `json:"kind"`
|
||||
Kind string `json:"kind"`
|
||||
}
|
||||
|
||||
// Output represents an output binding with a match to determine if the binding must be considered or not.
|
||||
|
@ -165,38 +112,14 @@ type Output struct {
|
|||
Match *Match `json:"match,omitempty"`
|
||||
}
|
||||
|
||||
// DefaultTimeouts contains defautl timeouts per operation.
|
||||
type DefaultTimeouts struct {
|
||||
// Apply defines the timeout for the apply operation
|
||||
// +optional
|
||||
// +kubebuilder:default:="5s"
|
||||
Apply metav1.Duration `json:"apply"`
|
||||
|
||||
// Assert defines the timeout for the assert operation
|
||||
// +optional
|
||||
// +kubebuilder:default:="30s"
|
||||
Assert metav1.Duration `json:"assert"`
|
||||
|
||||
// Cleanup defines the timeout for the cleanup operation
|
||||
// +optional
|
||||
// +kubebuilder:default:="30s"
|
||||
Cleanup metav1.Duration `json:"cleanup"`
|
||||
|
||||
// Delete defines the timeout for the delete operation
|
||||
// +optional
|
||||
// +kubebuilder:default:="15s"
|
||||
Delete metav1.Duration `json:"delete"`
|
||||
|
||||
// Error defines the timeout for the error operation
|
||||
// +optional
|
||||
// +kubebuilder:default:="30s"
|
||||
Error metav1.Duration `json:"error"`
|
||||
|
||||
// Exec defines the timeout for exec operations
|
||||
// +optional
|
||||
// +kubebuilder:default:="5s"
|
||||
Exec metav1.Duration `json:"exec"`
|
||||
}
|
||||
const (
|
||||
DefaultApplyTimeout = 5 * time.Second
|
||||
DefaultAssertTimeout = 30 * time.Second
|
||||
DefaultCleanupTimeout = 30 * time.Second
|
||||
DefaultDeleteTimeout = 15 * time.Second
|
||||
DefaultErrorTimeout = 30 * time.Second
|
||||
DefaultExecTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
// Timeouts contains timeouts per operation.
|
||||
type Timeouts struct {
|
||||
|
@ -218,3 +141,59 @@ type Timeouts struct {
|
|||
// Exec defines the timeout for exec operations
|
||||
Exec *metav1.Duration `json:"exec,omitempty"`
|
||||
}
|
||||
|
||||
func durationOrDefault(to *metav1.Duration, def time.Duration) time.Duration {
|
||||
if to != nil {
|
||||
return to.Duration
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func (t Timeouts) ApplyDuration() time.Duration {
|
||||
return durationOrDefault(t.Apply, DefaultApplyTimeout)
|
||||
}
|
||||
|
||||
func (t Timeouts) AssertDuration() time.Duration {
|
||||
return durationOrDefault(t.Assert, DefaultAssertTimeout)
|
||||
}
|
||||
|
||||
func (t Timeouts) CleanupDuration() time.Duration {
|
||||
return durationOrDefault(t.Cleanup, DefaultCleanupTimeout)
|
||||
}
|
||||
|
||||
func (t Timeouts) DeleteDuration() time.Duration {
|
||||
return durationOrDefault(t.Delete, DefaultDeleteTimeout)
|
||||
}
|
||||
|
||||
func (t Timeouts) ErrorDuration() time.Duration {
|
||||
return durationOrDefault(t.Error, DefaultErrorTimeout)
|
||||
}
|
||||
|
||||
func (t Timeouts) ExecDuration() time.Duration {
|
||||
return durationOrDefault(t.Exec, DefaultExecTimeout)
|
||||
}
|
||||
|
||||
func (t Timeouts) Combine(override *Timeouts) Timeouts {
|
||||
if override == nil {
|
||||
return t
|
||||
}
|
||||
if override.Apply != nil {
|
||||
t.Apply = override.Apply
|
||||
}
|
||||
if override.Assert != nil {
|
||||
t.Assert = override.Assert
|
||||
}
|
||||
if override.Error != nil {
|
||||
t.Error = override.Error
|
||||
}
|
||||
if override.Delete != nil {
|
||||
t.Delete = override.Delete
|
||||
}
|
||||
if override.Cleanup != nil {
|
||||
t.Cleanup = override.Cleanup
|
||||
}
|
||||
if override.Exec != nil {
|
||||
t.Exec = override.Exec
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
|
|
@ -2,15 +2,17 @@ package v1alpha1
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestBinding_CheckName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
bindingName Expression
|
||||
bindingValue Projection
|
||||
bindingName string
|
||||
bindingValue Any
|
||||
wantErr bool
|
||||
}{{
|
||||
name: "empty",
|
||||
|
@ -55,3 +57,97 @@ func TestBinding_CheckName(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_durationOrDefault(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
to *metav1.Duration
|
||||
def time.Duration
|
||||
want time.Duration
|
||||
}{{
|
||||
name: "nil",
|
||||
to: nil,
|
||||
def: time.Second * 3,
|
||||
want: time.Second * 3,
|
||||
}, {
|
||||
name: "not nil",
|
||||
to: &metav1.Duration{Duration: time.Second * 2},
|
||||
def: time.Second * 3,
|
||||
want: time.Second * 2,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := durationOrDefault(tt.to, tt.def)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeouts_Defaults(t *testing.T) {
|
||||
var timeouts Timeouts
|
||||
assert.Equal(t, DefaultApplyTimeout, timeouts.ApplyDuration())
|
||||
assert.Equal(t, DefaultAssertTimeout, timeouts.AssertDuration())
|
||||
assert.Equal(t, DefaultCleanupTimeout, timeouts.CleanupDuration())
|
||||
assert.Equal(t, DefaultDeleteTimeout, timeouts.DeleteDuration())
|
||||
assert.Equal(t, DefaultErrorTimeout, timeouts.ErrorDuration())
|
||||
assert.Equal(t, DefaultExecTimeout, timeouts.ExecDuration())
|
||||
}
|
||||
|
||||
func TestTimeouts_NoyDefaults(t *testing.T) {
|
||||
to := &metav1.Duration{Duration: time.Hour * 2}
|
||||
timeouts := Timeouts{
|
||||
Apply: to,
|
||||
Assert: to,
|
||||
Cleanup: to,
|
||||
Delete: to,
|
||||
Error: to,
|
||||
Exec: to,
|
||||
}
|
||||
assert.Equal(t, time.Hour*2, timeouts.ApplyDuration())
|
||||
assert.Equal(t, time.Hour*2, timeouts.AssertDuration())
|
||||
assert.Equal(t, time.Hour*2, timeouts.CleanupDuration())
|
||||
assert.Equal(t, time.Hour*2, timeouts.DeleteDuration())
|
||||
assert.Equal(t, time.Hour*2, timeouts.ErrorDuration())
|
||||
assert.Equal(t, time.Hour*2, timeouts.ExecDuration())
|
||||
}
|
||||
|
||||
func TestTimeouts_Combine(t *testing.T) {
|
||||
base := Timeouts{
|
||||
Apply: &metav1.Duration{Duration: 1 * time.Minute},
|
||||
Assert: &metav1.Duration{Duration: 1 * time.Minute},
|
||||
Cleanup: &metav1.Duration{Duration: 1 * time.Minute},
|
||||
Delete: &metav1.Duration{Duration: 1 * time.Minute},
|
||||
Error: &metav1.Duration{Duration: 1 * time.Minute},
|
||||
Exec: &metav1.Duration{Duration: 1 * time.Minute},
|
||||
}
|
||||
override := Timeouts{
|
||||
Apply: &metav1.Duration{Duration: 2 * time.Minute},
|
||||
Assert: &metav1.Duration{Duration: 2 * time.Minute},
|
||||
Cleanup: &metav1.Duration{Duration: 2 * time.Minute},
|
||||
Delete: &metav1.Duration{Duration: 2 * time.Minute},
|
||||
Error: &metav1.Duration{Duration: 2 * time.Minute},
|
||||
Exec: &metav1.Duration{Duration: 2 * time.Minute},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
base Timeouts
|
||||
override *Timeouts
|
||||
want Timeouts
|
||||
}{{
|
||||
name: "nil",
|
||||
base: base,
|
||||
override: nil,
|
||||
want: base,
|
||||
}, {
|
||||
name: "override",
|
||||
base: base,
|
||||
override: &override,
|
||||
want: override,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := tt.base.Combine(tt.override)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ limitations under the License.
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
policyv1alpha1 "github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
@ -99,11 +98,6 @@ func (in *ActionCheckRef) DeepCopy() *ActionCheckRef {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ActionClusters) DeepCopyInto(out *ActionClusters) {
|
||||
*out = *in
|
||||
if in.Cluster != nil {
|
||||
in, out := &in.Cluster, &out.Cluster
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Clusters != nil {
|
||||
in, out := &in.Clusters, &out.Clusters
|
||||
*out = make(Clusters, len(*in))
|
||||
|
@ -378,11 +372,6 @@ func (in *Assert) DeepCopy() *Assert {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Binding) DeepCopyInto(out *Binding) {
|
||||
*out = *in
|
||||
if in.Compiler != nil {
|
||||
in, out := &in.Compiler, &out.Compiler
|
||||
*out = new(policyv1alpha1.Compiler)
|
||||
**out = **in
|
||||
}
|
||||
in.Value.DeepCopyInto(&out.Value)
|
||||
return
|
||||
}
|
||||
|
@ -400,11 +389,6 @@ func (in *Binding) DeepCopy() *Binding {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CatchFinally) DeepCopyInto(out *CatchFinally) {
|
||||
*out = *in
|
||||
if in.Compiler != nil {
|
||||
in, out := &in.Compiler, &out.Compiler
|
||||
*out = new(policyv1alpha1.Compiler)
|
||||
**out = **in
|
||||
}
|
||||
if in.PodLogs != nil {
|
||||
in, out := &in.PodLogs, &out.PodLogs
|
||||
*out = new(PodLogs)
|
||||
|
@ -515,11 +499,6 @@ func (in *Command) DeepCopyInto(out *Command) {
|
|||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.WorkDir != nil {
|
||||
in, out := &in.WorkDir, &out.WorkDir
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -563,10 +542,10 @@ func (in *Configuration) DeepCopyObject() runtime.Object {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ConfigurationSpec) DeepCopyInto(out *ConfigurationSpec) {
|
||||
*out = *in
|
||||
out.Timeouts = in.Timeouts
|
||||
if in.Compiler != nil {
|
||||
in, out := &in.Compiler, &out.Compiler
|
||||
*out = new(policyv1alpha1.Compiler)
|
||||
in.Timeouts.DeepCopyInto(&out.Timeouts)
|
||||
if in.Template != nil {
|
||||
in, out := &in.Template, &out.Template
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.Parallel != nil {
|
||||
|
@ -574,11 +553,6 @@ func (in *ConfigurationSpec) DeepCopyInto(out *ConfigurationSpec) {
|
|||
*out = new(int)
|
||||
**out = **in
|
||||
}
|
||||
if in.NamespaceTemplateCompiler != nil {
|
||||
in, out := &in.NamespaceTemplateCompiler, &out.NamespaceTemplateCompiler
|
||||
*out = new(policyv1alpha1.Compiler)
|
||||
**out = **in
|
||||
}
|
||||
if in.NamespaceTemplate != nil {
|
||||
in, out := &in.NamespaceTemplate, &out.NamespaceTemplate
|
||||
*out = (*in).DeepCopy()
|
||||
|
@ -648,28 +622,6 @@ func (in *Create) DeepCopy() *Create {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DefaultTimeouts) DeepCopyInto(out *DefaultTimeouts) {
|
||||
*out = *in
|
||||
out.Apply = in.Apply
|
||||
out.Assert = in.Assert
|
||||
out.Cleanup = in.Cleanup
|
||||
out.Delete = in.Delete
|
||||
out.Error = in.Error
|
||||
out.Exec = in.Exec
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultTimeouts.
|
||||
func (in *DefaultTimeouts) DeepCopy() *DefaultTimeouts {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DefaultTimeouts)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Delete) DeepCopyInto(out *Delete) {
|
||||
*out = *in
|
||||
|
@ -988,11 +940,6 @@ func (in *OperationBase) DeepCopyInto(out *OperationBase) {
|
|||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.Compiler != nil {
|
||||
in, out := &in.Compiler, &out.Compiler
|
||||
*out = new(policyv1alpha1.Compiler)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1127,11 +1074,6 @@ func (in *Script) DeepCopyInto(out *Script) {
|
|||
in.ActionEnv.DeepCopyInto(&out.ActionEnv)
|
||||
in.ActionOutputs.DeepCopyInto(&out.ActionOutputs)
|
||||
in.ActionTimeout.DeepCopyInto(&out.ActionTimeout)
|
||||
if in.WorkDir != nil {
|
||||
in, out := &in.WorkDir, &out.WorkDir
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1270,21 +1212,11 @@ func (in *Test) DeepCopyObject() runtime.Object {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TestSpec) DeepCopyInto(out *TestSpec) {
|
||||
*out = *in
|
||||
if in.FailFast != nil {
|
||||
in, out := &in.FailFast, &out.FailFast
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.Timeouts != nil {
|
||||
in, out := &in.Timeouts, &out.Timeouts
|
||||
*out = new(Timeouts)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Cluster != nil {
|
||||
in, out := &in.Cluster, &out.Cluster
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Clusters != nil {
|
||||
in, out := &in.Clusters, &out.Clusters
|
||||
*out = make(Clusters, len(*in))
|
||||
|
@ -1312,20 +1244,10 @@ func (in *TestSpec) DeepCopyInto(out *TestSpec) {
|
|||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.Compiler != nil {
|
||||
in, out := &in.Compiler, &out.Compiler
|
||||
*out = new(policyv1alpha1.Compiler)
|
||||
**out = **in
|
||||
}
|
||||
if in.NamespaceTemplate != nil {
|
||||
in, out := &in.NamespaceTemplate, &out.NamespaceTemplate
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.NamespaceTemplateCompiler != nil {
|
||||
in, out := &in.NamespaceTemplateCompiler, &out.NamespaceTemplateCompiler
|
||||
*out = new(policyv1alpha1.Compiler)
|
||||
**out = **in
|
||||
}
|
||||
if in.Scenarios != nil {
|
||||
in, out := &in.Scenarios, &out.Scenarios
|
||||
*out = make([]Scenario, len(*in))
|
||||
|
@ -1385,11 +1307,6 @@ func (in *TestSpec) DeepCopy() *TestSpec {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TestStep) DeepCopyInto(out *TestStep) {
|
||||
*out = *in
|
||||
if in.Use != nil {
|
||||
in, out := &in.Use, &out.Use
|
||||
*out = new(Use)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
in.TestStepSpec.DeepCopyInto(&out.TestStepSpec)
|
||||
return
|
||||
}
|
||||
|
@ -1417,11 +1334,6 @@ func (in *TestStepSpec) DeepCopyInto(out *TestStepSpec) {
|
|||
*out = new(v1.DeletionPropagation)
|
||||
**out = **in
|
||||
}
|
||||
if in.Cluster != nil {
|
||||
in, out := &in.Cluster, &out.Cluster
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Clusters != nil {
|
||||
in, out := &in.Clusters, &out.Clusters
|
||||
*out = make(Clusters, len(*in))
|
||||
|
@ -1439,11 +1351,6 @@ func (in *TestStepSpec) DeepCopyInto(out *TestStepSpec) {
|
|||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.Compiler != nil {
|
||||
in, out := &in.Compiler, &out.Compiler
|
||||
*out = new(policyv1alpha1.Compiler)
|
||||
**out = **in
|
||||
}
|
||||
if in.Bindings != nil {
|
||||
in, out := &in.Bindings, &out.Bindings
|
||||
*out = make([]Binding, len(*in))
|
||||
|
@ -1561,23 +1468,6 @@ func (in *Update) DeepCopy() *Update {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Use) DeepCopyInto(out *Use) {
|
||||
*out = *in
|
||||
in.With.DeepCopyInto(&out.With)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Use.
|
||||
func (in *Use) DeepCopy() *Use {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Use)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Wait) DeepCopyInto(out *Wait) {
|
||||
*out = *in
|
||||
|
@ -1615,7 +1505,7 @@ func (in *WaitFor) DeepCopyInto(out *WaitFor) {
|
|||
if in.JsonPath != nil {
|
||||
in, out := &in.JsonPath, &out.JsonPath
|
||||
*out = new(WaitForJsonPath)
|
||||
(*in).DeepCopyInto(*out)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -1635,7 +1525,7 @@ func (in *WaitForCondition) DeepCopyInto(out *WaitForCondition) {
|
|||
*out = *in
|
||||
if in.Value != nil {
|
||||
in, out := &in.Value, &out.Value
|
||||
*out = new(Expression)
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
|
@ -1670,11 +1560,6 @@ func (in *WaitForDeletion) DeepCopy() *WaitForDeletion {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WaitForJsonPath) DeepCopyInto(out *WaitForJsonPath) {
|
||||
*out = *in
|
||||
if in.Value != nil {
|
||||
in, out := &in.Value, &out.Value
|
||||
*out = new(Expression)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1687,26 +1572,3 @@ func (in *WaitForJsonPath) DeepCopy() *WaitForJsonPath {
|
|||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *With) DeepCopyInto(out *With) {
|
||||
*out = *in
|
||||
if in.Bindings != nil {
|
||||
in, out := &in.Bindings, &out.Bindings
|
||||
*out = make([]Binding, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new With.
|
||||
func (in *With) DeepCopy() *With {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(With)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
|
@ -23,8 +20,8 @@ package v1alpha1
|
|||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName specifies the group name used to register the objects.
|
||||
|
@ -46,7 +43,7 @@ var (
|
|||
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// Deprecated: use Install instead
|
||||
// Depreciated: use Install instead
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
Install = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
package v1alpha2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// ActionCheck contains check for an action.
|
||||
type ActionCheck struct {
|
||||
// Check is an assertion tree to validate the operation outcome.
|
||||
// +optional
|
||||
Check *Check `json:"check,omitempty"`
|
||||
}
|
||||
|
||||
// ActionCheckRef contains check reference options for an action.
|
||||
type ActionCheckRef struct {
|
||||
FileRef `json:",inline"`
|
||||
|
||||
// Check provides a check used in assertions.
|
||||
// +optional
|
||||
Check *Check `json:"resource,omitempty"`
|
||||
|
||||
// Template determines whether resources should be considered for templating.
|
||||
// +optional
|
||||
Template *bool `json:"template,omitempty"`
|
||||
}
|
||||
|
||||
// ActionDryRun contains dry run options for an action.
|
||||
type ActionDryRun struct {
|
||||
// DryRun determines whether the file should be applied in dry run mode.
|
||||
// +optional
|
||||
DryRun *bool `json:"dryRun,omitempty"`
|
||||
}
|
||||
|
||||
// ActionEnv contains environment options for an action.
|
||||
type ActionEnv struct {
|
||||
// Env defines additional environment variables.
|
||||
// +optional
|
||||
Env []Binding `json:"env,omitempty"`
|
||||
|
||||
// SkipLogOutput removes the output from the command. Useful for sensitive logs or to reduce noise.
|
||||
// +optional
|
||||
SkipLogOutput bool `json:"skipLogOutput,omitempty"`
|
||||
}
|
||||
|
||||
// ActionExpectations contains expectations for an action.
|
||||
type ActionExpectations struct {
|
||||
// Expect defines a list of matched checks to validate the operation outcome.
|
||||
// +optional
|
||||
Expect []Expectation `json:"expect,omitempty"`
|
||||
}
|
||||
|
||||
// ActionFormat contains format for an action.
|
||||
type ActionFormat struct {
|
||||
// Format determines the output format (json or yaml).
|
||||
// +optional
|
||||
Format Format `json:"format,omitempty"`
|
||||
}
|
||||
|
||||
type ActionInlineResource struct {
|
||||
// Resource provides a resource to be applied.
|
||||
// +kubebuilder:validation:XEmbeddedResource
|
||||
// +kubebuilder:pruning:PreserveUnknownFields
|
||||
// +optional
|
||||
Resource *unstructured.Unstructured `json:"resource,omitempty"`
|
||||
}
|
||||
|
||||
// ActionObject contains object selector options for an action.
|
||||
type ActionObject struct {
|
||||
ObjectType `json:",inline"`
|
||||
ActionObjectSelector `json:",inline"`
|
||||
}
|
||||
|
||||
// ActionObjectSelector contains object selector options for an action.
|
||||
type ActionObjectSelector struct {
|
||||
ObjectName `json:",inline"`
|
||||
|
||||
// Selector defines labels selector.
|
||||
// +optional
|
||||
Selector string `json:"selector,omitempty"`
|
||||
}
|
||||
|
||||
// FileRef represents a file reference.
|
||||
type FileRef struct {
|
||||
// File is the path to the referenced file. This can be a direct path to a file
|
||||
// or an expression that matches multiple files, such as "manifest/*.yaml" for all YAML
|
||||
// files within the "manifest" directory.
|
||||
File string `json:"file,omitempty"`
|
||||
}
|
||||
|
||||
// ActionResourceRef contains resource reference options for an action.
|
||||
type ActionResourceRef struct {
|
||||
FileRef `json:",inline"`
|
||||
// Resource provides a resource to be applied.
|
||||
// +kubebuilder:validation:XEmbeddedResource
|
||||
// +kubebuilder:pruning:PreserveUnknownFields
|
||||
// +optional
|
||||
Resource *unstructured.Unstructured `json:"resource,omitempty"`
|
||||
// ActionInlineResource `json:",inline"`
|
||||
|
||||
// Template determines whether resources should be considered for templating.
|
||||
// +optional
|
||||
Template *bool `json:"template,omitempty"`
|
||||
}
|
||||
|
||||
// ActionTimeout contains timeout options for an action.
|
||||
type ActionTimeout struct {
|
||||
// Timeout for the operation. Overrides the global timeout set in the Configuration.
|
||||
// +optional
|
||||
Timeout *metav1.Duration `json:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
// Apply represents a set of configurations or resources that
|
||||
// should be applied during testing.
|
||||
// +k8s:conversion-gen=false
|
||||
type Apply struct {
|
||||
ActionDryRun `json:",inline"`
|
||||
ActionExpectations `json:",inline"`
|
||||
ActionResourceRef `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
}
|
||||
|
||||
// Assert represents a test condition that is expected to hold true
|
||||
// during the testing process.
|
||||
// +k8s:conversion-gen=false
|
||||
type Assert struct {
|
||||
ActionCheckRef `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
}
|
||||
|
||||
// Command describes a command to run as a part of a test step.
|
||||
// +k8s:conversion-gen=false
|
||||
type Command struct {
|
||||
ActionCheck `json:",inline"`
|
||||
ActionEnv `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
|
||||
// Entrypoint is the command entry point to run.
|
||||
Entrypoint string `json:"entrypoint"`
|
||||
|
||||
// Args is the command arguments.
|
||||
// +optional
|
||||
Args []string `json:"args,omitempty"`
|
||||
}
|
||||
|
||||
// Create represents a set of resources that should be created.
|
||||
// If a resource already exists in the cluster it will fail.
|
||||
// +k8s:conversion-gen=false
|
||||
type Create struct {
|
||||
ActionDryRun `json:",inline"`
|
||||
ActionExpectations `json:",inline"`
|
||||
ActionResourceRef `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
}
|
||||
|
||||
// Delete is a reference to an object that should be deleted
|
||||
// +k8s:conversion-gen=false
|
||||
type Delete struct {
|
||||
ActionExpectations `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
|
||||
// Template determines whether resources should be considered for templating.
|
||||
// +optional
|
||||
Template *bool `json:"template,omitempty"`
|
||||
|
||||
// File is the path to the referenced file. This can be a direct path to a file
|
||||
// or an expression that matches multiple files, such as "manifest/*.yaml" for all YAML
|
||||
// files within the "manifest" directory.
|
||||
// +optional
|
||||
File string `json:"file,omitempty"`
|
||||
|
||||
// Ref determines objects to be deleted.
|
||||
// +optional
|
||||
Ref *ObjectReference `json:"ref,omitempty"`
|
||||
|
||||
// DeletionPropagationPolicy decides if a deletion will propagate to the dependents of
|
||||
// the object, and how the garbage collector will handle the propagation.
|
||||
// Overrides the deletion propagation policy set in the Configuration, the Test and the TestStep.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Enum:=Orphan;Background;Foreground
|
||||
DeletionPropagationPolicy *metav1.DeletionPropagation `json:"deletionPropagationPolicy,omitempty"`
|
||||
}
|
||||
|
||||
// Describe defines how to describe resources.
|
||||
// +k8s:conversion-gen=false
|
||||
type Describe struct {
|
||||
ActionObject `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
|
||||
// Show Events indicates whether to include related events.
|
||||
// +optional
|
||||
ShowEvents *bool `json:"showEvents,omitempty"`
|
||||
}
|
||||
|
||||
// Error represents an anticipated error condition that may arise during testing.
|
||||
// Instead of treating such an error as a test failure, it acknowledges it as expected.
|
||||
// +k8s:conversion-gen=false
|
||||
type Error struct {
|
||||
ActionCheckRef `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
}
|
||||
|
||||
// Events defines how to collect events.
|
||||
// +k8s:conversion-gen=false
|
||||
type Events struct {
|
||||
ActionFormat `json:",inline"`
|
||||
ActionObjectSelector `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
}
|
||||
|
||||
// Get defines how to get resources.
|
||||
// +k8s:conversion-gen=false
|
||||
type Get struct {
|
||||
ActionFormat `json:",inline"`
|
||||
ActionObject `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
}
|
||||
|
||||
// Patch represents a set of resources that should be patched.
|
||||
// If a resource doesn't exist yet in the cluster it will fail.
|
||||
// +k8s:conversion-gen=false
|
||||
type Patch struct {
|
||||
ActionDryRun `json:",inline"`
|
||||
ActionExpectations `json:",inline"`
|
||||
ActionResourceRef `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
}
|
||||
|
||||
// PodLogs defines how to collect pod logs.
|
||||
// +k8s:conversion-gen=false
|
||||
type PodLogs struct {
|
||||
ActionObjectSelector `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
|
||||
// Container in pod to get logs from else --all-containers is used.
|
||||
// +optional
|
||||
Container string `json:"container,omitempty"`
|
||||
|
||||
// Tail is the number of last lines to collect from pods. If omitted or zero,
|
||||
// then the default is 10 if you use a selector, or -1 (all) if you use a pod name.
|
||||
// This matches default behavior of `kubectl logs`.
|
||||
// +optional
|
||||
Tail *int `json:"tail,omitempty"`
|
||||
}
|
||||
|
||||
// Script describes a script to run as a part of a test step.
|
||||
// +k8s:conversion-gen=false
|
||||
type Script struct {
|
||||
ActionCheck `json:",inline"`
|
||||
ActionEnv `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
|
||||
// Content defines a shell script (run with "sh -c ...").
|
||||
// +optional
|
||||
Content string `json:"content,omitempty"`
|
||||
}
|
||||
|
||||
// Sleep represents a duration while nothing happens.
|
||||
// +k8s:conversion-gen=false
|
||||
type Sleep struct {
|
||||
// Duration is the delay used for sleeping.
|
||||
Duration metav1.Duration `json:"duration"`
|
||||
}
|
||||
|
||||
// Update represents a set of resources that should be updated.
|
||||
// If a resource does not exist in the cluster it will fail.
|
||||
// +k8s:conversion-gen=false
|
||||
type Update struct {
|
||||
ActionDryRun `json:",inline"`
|
||||
ActionExpectations `json:",inline"`
|
||||
ActionResourceRef `json:",inline"`
|
||||
ActionTimeout `json:",inline"`
|
||||
}
|
||||
|
||||
// Wait specifies how to perform wait operations on resources.
|
||||
// +k8s:conversion-gen=false
|
||||
type Wait struct {
|
||||
ActionTimeout `json:",inline"`
|
||||
ActionFormat `json:",inline"`
|
||||
ActionObject `json:",inline"`
|
||||
|
||||
// WaitFor specifies the condition to wait for.
|
||||
WaitFor `json:"for"`
|
||||
}
|
||||
|
||||
// WaitFor specifies the condition to wait for.
|
||||
// +k8s:conversion-gen=false
|
||||
type WaitFor struct {
|
||||
// Deletion specifies parameters for waiting on a resource's deletion.
|
||||
// +optional
|
||||
Deletion *WaitForDeletion `json:"deletion,omitempty"`
|
||||
|
||||
// Condition specifies the condition to wait for.
|
||||
// +optional
|
||||
Condition *WaitForCondition `json:"condition,omitempty"`
|
||||
|
||||
// JsonPath specifies the json path condition to wait for.
|
||||
// +optional
|
||||
JsonPath *WaitForJsonPath `json:"jsonPath,omitempty"`
|
||||
}
|
||||
|
||||
// WaitForCondition represents parameters for waiting on a specific condition of a resource.
|
||||
// +k8s:conversion-gen=false
|
||||
type WaitForCondition struct {
|
||||
// Name defines the specific condition to wait for, e.g., "Available", "Ready".
|
||||
Name string `json:"name"`
|
||||
|
||||
// Value defines the specific condition status to wait for, e.g., "True", "False".
|
||||
// +optional
|
||||
Value *string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
// WaitForDeletion represents parameters for waiting on a resource's deletion.
|
||||
// +k8s:conversion-gen=false
|
||||
type WaitForDeletion struct{}
|
||||
|
||||
// WaitForJsonPath represents parameters for waiting on a json path of a resource.
|
||||
// +k8s:conversion-gen=false
|
||||
type WaitForJsonPath struct {
|
||||
// Path defines the json path to wait for, e.g. '{.status.phase}'.
|
||||
Path string `json:"path"`
|
||||
|
||||
// Value defines the expected value to wait for, e.g., "Running".
|
||||
Value string `json:"value"`
|
||||
}
|
|
@ -71,5 +71,5 @@ type ConfigurationSpec struct {
|
|||
// Global timeouts configuration. Applies to all tests/test steps if not overridden.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
Timeouts DefaultTimeouts `json:"timeouts"`
|
||||
Timeouts Timeouts `json:"timeouts"`
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
package v1alpha2
|
||||
|
||||
// Operation defines operation elements.
|
||||
// +k8s:conversion-gen=false
|
||||
type Operation struct {
|
||||
OperationAction `json:",inline"`
|
||||
OperationBindings `json:",inline"`
|
||||
OperationClusters `json:",inline"`
|
||||
OperationOutputs `json:",inline"`
|
||||
|
||||
// Description contains a description of the operation.
|
||||
// +optional
|
||||
Description string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// OperationAction defines an operation action, only one action should be specified per operation.
|
||||
type OperationAction struct {
|
||||
// Apply represents resources that should be applied for this test step. This can include things
|
||||
// like configuration settings or any other resources that need to be available during the test.
|
||||
// +optional
|
||||
Apply *Apply `json:"apply,omitempty"`
|
||||
|
||||
// Assert represents an assertion to be made. It checks whether the conditions specified in the assertion hold true.
|
||||
// +optional
|
||||
Assert *Assert `json:"assert,omitempty"`
|
||||
|
||||
// Command defines a command to run.
|
||||
// +optional
|
||||
Command *Command `json:"command,omitempty"`
|
||||
|
||||
// Create represents a creation operation.
|
||||
// +optional
|
||||
Create *Create `json:"create,omitempty"`
|
||||
|
||||
// Delete represents a deletion operation.
|
||||
// +optional
|
||||
Delete *Delete `json:"delete,omitempty"`
|
||||
|
||||
// Describe determines the resource describe collector to execute.
|
||||
// +optional
|
||||
Describe *Describe `json:"describe,omitempty"`
|
||||
|
||||
// Error represents the expected errors for this test step. If any of these errors occur, the test
|
||||
// will consider them as expected; otherwise, they will be treated as test failures.
|
||||
// +optional
|
||||
Error *Error `json:"error,omitempty"`
|
||||
|
||||
// Events determines the events collector to execute.
|
||||
// +optional
|
||||
Events *Events `json:"events,omitempty"`
|
||||
|
||||
// Get determines the resource get collector to execute.
|
||||
// +optional
|
||||
Get *Get `json:"get,omitempty"`
|
||||
|
||||
// Patch represents a patch operation.
|
||||
// +optional
|
||||
Patch *Patch `json:"patch,omitempty"`
|
||||
|
||||
// PodLogs determines the pod logs collector to execute.
|
||||
// +optional
|
||||
PodLogs *PodLogs `json:"podLogs,omitempty"`
|
||||
|
||||
// Script defines a script to run.
|
||||
// +optional
|
||||
Script *Script `json:"script,omitempty"`
|
||||
|
||||
// Sleep defines zzzz.
|
||||
// +optional
|
||||
Sleep *Sleep `json:"sleep,omitempty"`
|
||||
|
||||
// Update represents an update operation.
|
||||
// +optional
|
||||
Update *Update `json:"update,omitempty"`
|
||||
|
||||
// Wait determines the resource wait collector to execute.
|
||||
// +optional
|
||||
Wait *Wait `json:"wait,omitempty"`
|
||||
}
|
||||
|
||||
// OperationBindings contains bindings options for an operation.
|
||||
type OperationBindings struct {
|
||||
// Bindings defines additional binding key/values.
|
||||
// +optional
|
||||
Bindings []Binding `json:"bindings,omitempty"`
|
||||
}
|
||||
|
||||
// OperationClusters contains clusters options for an operation.
|
||||
type OperationClusters struct {
|
||||
// Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).
|
||||
// +optional
|
||||
Cluster string `json:"cluster,omitempty"`
|
||||
|
||||
// Clusters holds a registry to clusters to support multi-cluster tests.
|
||||
// +optional
|
||||
Clusters Clusters `json:"clusters,omitempty"`
|
||||
}
|
||||
|
||||
// OperationOutputs contains outputs options for an operation.
|
||||
type OperationOutputs struct {
|
||||
// Outputs defines output bindings.
|
||||
// +optional
|
||||
Outputs []Output `json:"outputs,omitempty"`
|
||||
}
|
||||
|
||||
// TryOperation defines operation elements.
|
||||
// +k8s:conversion-gen=false
|
||||
type TryOperation struct {
|
||||
Operation `json:",inline"`
|
||||
|
||||
// ContinueOnError determines whether a test should continue or not in case the operation was not successful.
|
||||
// Even if the test continues executing, it will still be reported as failed.
|
||||
// +optional
|
||||
ContinueOnError *bool `json:"continueOnError,omitempty"`
|
||||
}
|
|
@ -2,6 +2,7 @@ package v1alpha2
|
|||
|
||||
import (
|
||||
"github.com/kyverno/chainsaw/pkg/apis/v1alpha1"
|
||||
_ "github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
|
@ -86,30 +87,23 @@ type NamespaceOptions struct {
|
|||
// +optional
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Compiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
Compiler *Compiler `json:"compiler,omitempty"`
|
||||
|
||||
// Template defines a template to create the test namespace.
|
||||
// +optional
|
||||
Template *Projection `json:"template,omitempty"`
|
||||
Template *Any `json:"template,omitempty"`
|
||||
}
|
||||
|
||||
type ReportFormatType string
|
||||
|
||||
const (
|
||||
JSONFormat ReportFormatType = "JSON"
|
||||
XMLFormat ReportFormatType = "XML"
|
||||
JUnitTestFormat ReportFormatType = "JUNIT-TEST"
|
||||
JUnitStepFormat ReportFormatType = "JUNIT-STEP"
|
||||
JUnitOperationFormat ReportFormatType = "JUNIT-OPERATION"
|
||||
JSONFormat ReportFormatType = "JSON"
|
||||
XMLFormat ReportFormatType = "XML"
|
||||
)
|
||||
|
||||
// ReportOptions contains the configuration used for reporting.
|
||||
type ReportOptions struct {
|
||||
// ReportFormat determines test report format (JSON, XML, JUNIT-TEST, JUNIT-STEP, JUNIT-OPERATION).
|
||||
// ReportFormat determines test report format (JSON|XML).
|
||||
// +optional
|
||||
// +kubebuilder:validation:Enum:=JSON;XML;JUNIT-TEST;JUNIT-STEP;JUNIT-OPERATION
|
||||
// +kubebuilder:validation:Enum:=JSON;XML
|
||||
// +kubebuilder:default:="JSON"
|
||||
Format ReportFormatType `json:"format,omitempty"`
|
||||
|
||||
|
@ -129,8 +123,4 @@ type TemplatingOptions struct {
|
|||
// +optional
|
||||
// +kubebuilder:default:=true
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Compiler defines the default compiler to use when evaluating expressions.
|
||||
// +optional
|
||||
Compiler *Compiler `json:"compiler,omitempty"`
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package v1alpha2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// TestStep contains the test step definition used in a test spec.
|
||||
// +k8s:conversion-gen=false
|
||||
type TestStep struct {
|
||||
// Name of the step.
|
||||
// +optional
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// TestStepSpec of the step.
|
||||
TestStepSpec `json:",inline"`
|
||||
}
|
||||
|
||||
// TestStepSpec defines the desired state and behavior for each test step.
|
||||
// +k8s:conversion-gen=false
|
||||
type TestStepSpec struct {
|
||||
// Description contains a description of the test step.
|
||||
// +optional
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Timeouts for the test step. Overrides the global timeouts set in the Configuration and the timeouts eventually set in the Test.
|
||||
// +optional
|
||||
Timeouts *Timeouts `json:"timeouts,omitempty"`
|
||||
|
||||
// DeletionPropagationPolicy decides if a deletion will propagate to the dependents of
|
||||
// the object, and how the garbage collector will handle the propagation.
|
||||
// Overrides the deletion propagation policy set in both the Configuration and the Test.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Enum:=Orphan;Background;Foreground
|
||||
DeletionPropagationPolicy *metav1.DeletionPropagation `json:"deletionPropagationPolicy,omitempty"`
|
||||
|
||||
// Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).
|
||||
// +optional
|
||||
Cluster string `json:"cluster,omitempty"`
|
||||
|
||||
// Clusters holds a registry to clusters to support multi-cluster tests.
|
||||
// +optional
|
||||
Clusters Clusters `json:"clusters,omitempty"`
|
||||
|
||||
// SkipDelete determines whether the resources created by the step should be deleted after the test step is executed.
|
||||
// +optional
|
||||
SkipDelete *bool `json:"skipDelete,omitempty"`
|
||||
|
||||
// Template determines whether resources should be considered for templating.
|
||||
// +optional
|
||||
Template *bool `json:"template,omitempty"`
|
||||
|
||||
// Bindings defines additional binding key/values.
|
||||
// +optional
|
||||
Bindings []Binding `json:"bindings,omitempty"`
|
||||
|
||||
// Try defines what the step will try to execute.
|
||||
// +kubebuilder:validation:MinItems:=1
|
||||
Try []TryOperation `json:"try"`
|
||||
|
||||
// Catch defines what the step will execute when an error happens.
|
||||
// +optional
|
||||
Catch []Operation `json:"catch,omitempty"`
|
||||
|
||||
// Finally defines what the step will execute after the step is terminated.
|
||||
// +optional
|
||||
Finally []Operation `json:"finally,omitempty"`
|
||||
|
||||
// Cleanup defines what will be executed after the test is terminated.
|
||||
// +optional
|
||||
Cleanup []Operation `json:"cleanup,omitempty"`
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package v1alpha2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:resource:scope=Cluster
|
||||
|
||||
// Test is the resource that contains a test definition.
|
||||
type Test struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// Standard object's metadata.
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Test spec.
|
||||
Spec TestSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// TestSpec contains the test spec.
|
||||
// +k8s:conversion-gen=false
|
||||
type TestSpec struct {
|
||||
// Cleanup contains cleanup configuration.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
Cleanup CleanupOptions `json:"cleanup"`
|
||||
|
||||
// Cluster defines the target cluster (default cluster will be used if not specified and/or overridden).
|
||||
// +optional
|
||||
Cluster string `json:"cluster,omitempty"`
|
||||
|
||||
// Clusters holds a registry to clusters to support multi-cluster tests.
|
||||
// +optional
|
||||
Clusters Clusters `json:"clusters,omitempty"`
|
||||
|
||||
// Execution contains tests execution configuration.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
Execution TestExecutionOptions `json:"execution"`
|
||||
|
||||
// Bindings defines additional binding key/values.
|
||||
// +optional
|
||||
Bindings []Binding `json:"bindings,omitempty"`
|
||||
|
||||
// Deletion contains the global deletion configuration.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
Deletion DeletionOptions `json:"deletion"`
|
||||
|
||||
// Description contains a description of the test.
|
||||
// +optional
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Error contains the global error configuration.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
Error ErrorOptions `json:"error"`
|
||||
|
||||
// Namespace contains properties for the namespace to use for tests.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
Namespace NamespaceOptions `json:"namespace"`
|
||||
|
||||
// Steps defining the test.
|
||||
Steps []TestStep `json:"steps"`
|
||||
|
||||
// Templating contains the templating config.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
Templating TemplatingOptions `json:"templating"`
|
||||
|
||||
// Timeouts for the test. Overrides the global timeouts set in the Configuration on a per operation basis.
|
||||
// +optional
|
||||
// +kubebuilder:default:={}
|
||||
Timeouts Timeouts `json:"timeouts"`
|
||||
}
|
||||
|
||||
// TestExecutionOptions determines how tests are run.
|
||||
type TestExecutionOptions struct {
|
||||
// Concurrent determines whether the test should run concurrently with other tests.
|
||||
// +optional
|
||||
// +kubebuilder:default:=true
|
||||
Concurrent bool `json:"concurrent"`
|
||||
|
||||
// Skip determines whether the test should skipped.
|
||||
// +optional
|
||||
Skip bool `json:"skip,omitempty"`
|
||||
|
||||
// TerminationGracePeriod forces the termination grace period on pods, statefulsets, daemonsets and deployments.
|
||||
// +optional
|
||||
TerminationGracePeriod *metav1.Duration `json:"terminationGracePeriod,omitempty"`
|
||||
}
|
|
@ -3,16 +3,32 @@ package v1alpha2
|
|||
import (
|
||||
"github.com/kyverno/chainsaw/pkg/apis/v1alpha1"
|
||||
_ "github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
EngineJP = v1alpha1.EngineJP
|
||||
EngineCEL = v1alpha1.EngineCEL
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type (
|
||||
Clusters = v1alpha1.Clusters
|
||||
Compiler = v1alpha1.Compiler
|
||||
DefaultTimeouts = v1alpha1.DefaultTimeouts
|
||||
Projection = v1alpha1.Projection
|
||||
Any = v1alpha1.Any
|
||||
Binding = v1alpha1.Binding
|
||||
Check = v1alpha1.Check
|
||||
Cluster = v1alpha1.Cluster
|
||||
Clusters = v1alpha1.Clusters
|
||||
Expectation = v1alpha1.Expectation
|
||||
Format = v1alpha1.Format
|
||||
ObjectName = v1alpha1.ObjectName
|
||||
ObjectType = v1alpha1.ObjectType
|
||||
Output = v1alpha1.Output
|
||||
Timeouts = v1alpha1.Timeouts
|
||||
)
|
||||
|
||||
// ObjectReference represents one or more objects with a specific apiVersion and kind.
|
||||
// For a single object name and namespace are used to identify the object.
|
||||
// For multiple objects use labels.
|
||||
// +k8s:conversion-gen=false
|
||||
type ObjectReference struct {
|
||||
ObjectType `json:",inline"`
|
||||
ObjectName `json:",inline"`
|
||||
|
||||
// Label selector to match objects to delete
|
||||
// +optional
|
||||
Labels *metav1.LabelSelector `json:"labelSelector,omitempty"`
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,3 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
|
@ -23,8 +20,8 @@ package v1alpha2
|
|||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName specifies the group name used to register the objects.
|
||||
|
@ -46,7 +43,7 @@ var (
|
|||
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// Deprecated: use Install instead
|
||||
// Depreciated: use Install instead
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
Install = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
@ -62,6 +59,7 @@ func init() {
|
|||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Configuration{},
|
||||
&Test{},
|
||||
)
|
||||
// AddToGroupVersion allows the serialization of client types like ListOptions.
|
||||
v1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
package cleaner
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/client"
|
||||
"github.com/kyverno/chainsaw/pkg/model"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type cleanupEntry struct {
|
||||
client client.Client
|
||||
object client.Object
|
||||
}
|
||||
|
||||
type CleanerCollector interface {
|
||||
Empty() bool
|
||||
Add(client.Client, client.Object)
|
||||
}
|
||||
|
||||
type Cleaner interface {
|
||||
CleanerCollector
|
||||
Run(ctx context.Context, stepReport *model.StepReport) []error
|
||||
}
|
||||
|
||||
func New(timeout time.Duration, delay *time.Duration, propagation metav1.DeletionPropagation) Cleaner {
|
||||
return &cleaner{
|
||||
delay: delay,
|
||||
timeout: timeout,
|
||||
propagation: propagation,
|
||||
}
|
||||
}
|
||||
|
||||
type cleaner struct {
|
||||
delay *time.Duration
|
||||
timeout time.Duration
|
||||
propagation metav1.DeletionPropagation
|
||||
entries []cleanupEntry
|
||||
}
|
||||
|
||||
func (c *cleaner) Add(client client.Client, object client.Object) {
|
||||
c.entries = append(c.entries, cleanupEntry{
|
||||
client: client,
|
||||
object: object,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *cleaner) Empty() bool {
|
||||
return len(c.entries) == 0
|
||||
}
|
||||
|
||||
func (c *cleaner) Run(ctx context.Context, stepReport *model.StepReport) []error {
|
||||
if c.delay != nil {
|
||||
time.Sleep(*c.delay)
|
||||
}
|
||||
var errs []error
|
||||
for i := len(c.entries) - 1; i >= 0; i-- {
|
||||
report := model.OperationReport{
|
||||
Type: model.OperationTypeDelete,
|
||||
StartTime: time.Now(),
|
||||
}
|
||||
if report.Err = c.delete(ctx, c.entries[i]); report.Err != nil {
|
||||
errs = append(errs, report.Err)
|
||||
}
|
||||
report.EndTime = time.Now()
|
||||
if stepReport != nil {
|
||||
stepReport.Add(&report)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func (c *cleaner) delete(ctx context.Context, entry cleanupEntry) error {
|
||||
if c.timeout != 0 {
|
||||
_ctx, cancel := context.WithTimeout(ctx, c.timeout)
|
||||
defer cancel()
|
||||
ctx = _ctx
|
||||
}
|
||||
if err := entry.client.Delete(ctx, entry.object, client.PropagationPolicy(c.propagation)); err != nil {
|
||||
if !kerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
} else if err := client.WaitForDeletion(ctx, entry.client, entry.object); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,204 +0,0 @@
|
|||
package cleaner
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/client"
|
||||
tclient "github.com/kyverno/chainsaw/pkg/client/testing"
|
||||
"github.com/kyverno/chainsaw/pkg/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kerror "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/utils/ptr"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
timeout time.Duration
|
||||
delay *time.Duration
|
||||
want Cleaner
|
||||
}{{
|
||||
name: "with timeout",
|
||||
timeout: time.Minute,
|
||||
delay: nil,
|
||||
want: &cleaner{
|
||||
timeout: time.Minute,
|
||||
delay: nil,
|
||||
propagation: metav1.DeletePropagationBackground,
|
||||
},
|
||||
}, {
|
||||
name: "with delay",
|
||||
timeout: time.Minute,
|
||||
delay: ptr.To(10 * time.Second),
|
||||
want: &cleaner{
|
||||
timeout: time.Minute,
|
||||
delay: ptr.To(10 * time.Second),
|
||||
propagation: metav1.DeletePropagationBackground,
|
||||
},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := New(tt.timeout, tt.delay, metav1.DeletePropagationBackground)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_cleaner_Empty(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
entries []cleanupEntry
|
||||
want bool
|
||||
}{{
|
||||
name: "without entries",
|
||||
entries: nil,
|
||||
want: true,
|
||||
}, {
|
||||
name: "without entries",
|
||||
entries: []cleanupEntry{},
|
||||
want: true,
|
||||
}, {
|
||||
name: "with entries",
|
||||
entries: []cleanupEntry{{}},
|
||||
want: false,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &cleaner{
|
||||
entries: tt.entries,
|
||||
}
|
||||
got := c.Empty()
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_cleaner_Add(t *testing.T) {
|
||||
entry := cleanupEntry{
|
||||
object: &unstructured.Unstructured{},
|
||||
client: &tclient.FakeClient{},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
entries []cleanupEntry
|
||||
client client.Client
|
||||
object client.Object
|
||||
want []cleanupEntry
|
||||
}{{
|
||||
name: "empty",
|
||||
client: entry.client,
|
||||
object: entry.object,
|
||||
want: []cleanupEntry{entry},
|
||||
}, {
|
||||
name: "with entries",
|
||||
entries: []cleanupEntry{entry},
|
||||
client: entry.client,
|
||||
object: entry.object,
|
||||
want: []cleanupEntry{entry, entry},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &cleaner{
|
||||
entries: tt.entries,
|
||||
}
|
||||
c.Add(tt.client, tt.object)
|
||||
assert.Equal(t, tt.want, c.entries)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_cleaner_Run(t *testing.T) {
|
||||
obj := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
entries []cleanupEntry
|
||||
want []error
|
||||
}{{
|
||||
name: "empty",
|
||||
}, {
|
||||
name: "ok",
|
||||
entries: []cleanupEntry{{
|
||||
object: obj,
|
||||
client: &tclient.FakeClient{
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
return nil
|
||||
},
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
return kerror.NewNotFound(corev1.Resource("namespace"), "foo")
|
||||
},
|
||||
},
|
||||
}},
|
||||
want: nil,
|
||||
}, {
|
||||
name: "not found",
|
||||
entries: []cleanupEntry{{
|
||||
object: obj,
|
||||
client: &tclient.FakeClient{
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
return kerror.NewNotFound(corev1.Resource("namespace"), "foo")
|
||||
},
|
||||
},
|
||||
}},
|
||||
want: nil,
|
||||
}, {
|
||||
name: "delete error",
|
||||
entries: []cleanupEntry{{
|
||||
object: obj,
|
||||
client: &tclient.FakeClient{
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
return errors.New("dummy")
|
||||
},
|
||||
},
|
||||
}},
|
||||
want: []error{errors.New("dummy")},
|
||||
}, {
|
||||
name: "get error",
|
||||
entries: []cleanupEntry{{
|
||||
object: obj,
|
||||
client: &tclient.FakeClient{
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
return nil
|
||||
},
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
return errors.New("dummy")
|
||||
},
|
||||
},
|
||||
}},
|
||||
want: []error{errors.New("dummy")},
|
||||
}, {
|
||||
name: "failed",
|
||||
entries: []cleanupEntry{{
|
||||
object: obj,
|
||||
client: &tclient.FakeClient{
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
return nil
|
||||
},
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}},
|
||||
want: []error{context.DeadlineExceeded},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &cleaner{
|
||||
delay: ptr.To(time.Second),
|
||||
timeout: 1 * time.Second,
|
||||
entries: tt.entries,
|
||||
}
|
||||
got := c.Run(context.TODO(), &model.StepReport{})
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package simple
|
||||
package client
|
||||
|
||||
import (
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth" // package needed for auth providers like GCP
|
|
@ -5,33 +5,35 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/rest"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
// Get retrieves an obj for the given object key from the Kubernetes Cluster.
|
||||
// obj must be a struct pointer so that obj can be updated with the response
|
||||
// returned by the Server.
|
||||
Get(ctx context.Context, key ObjectKey, obj Object, opts ...GetOption) error
|
||||
Get(ctx context.Context, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error
|
||||
|
||||
// List retrieves list of objects for a given namespace and list options. On a
|
||||
// successful call, Items field in the list will be populated with the
|
||||
// result returned from the server.
|
||||
List(ctx context.Context, list ObjectList, opts ...ListOption) error
|
||||
List(ctx context.Context, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error
|
||||
|
||||
// Create saves the object obj in the Kubernetes cluster. obj must be a
|
||||
// struct pointer so that obj can be updated with the content returned by the Server.
|
||||
Create(ctx context.Context, obj Object, opts ...CreateOption) error
|
||||
Create(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error
|
||||
|
||||
// Update updates the given obj in the Kubernetes cluster. obj must be a
|
||||
// struct pointer so that obj can be updated with the content returned by the Server.
|
||||
Update(ctx context.Context, obj Object, opts ...UpdateOption) error
|
||||
Update(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error
|
||||
|
||||
// Delete deletes the given obj from Kubernetes cluster.
|
||||
Delete(ctx context.Context, obj Object, opts ...DeleteOption) error
|
||||
Delete(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error
|
||||
|
||||
// Patch patches the given obj in the Kubernetes cluster. obj must be a
|
||||
// struct pointer so that obj can be updated with the content returned by the Server.
|
||||
Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error
|
||||
Patch(ctx context.Context, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error
|
||||
|
||||
// IsObjectNamespaced returns true if the GroupVersionKind of the object is namespaced.
|
||||
IsObjectNamespaced(obj runtime.Object) (bool, error)
|
||||
|
@ -39,3 +41,8 @@ type Client interface {
|
|||
// RESTMapper returns the rest this client is using.
|
||||
RESTMapper() meta.RESTMapper
|
||||
}
|
||||
|
||||
func New(cfg *rest.Config) (Client, error) {
|
||||
var opts ctrlclient.Options
|
||||
return ctrlclient.New(cfg, opts)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package simple
|
||||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -1,31 +1,28 @@
|
|||
package dryrun
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/client"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
type Client = client.Client
|
||||
|
||||
type dryRunClient struct {
|
||||
inner Client
|
||||
}
|
||||
|
||||
func (c *dryRunClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {
|
||||
return c.inner.Create(ctx, obj, append(opts, ctrlclient.DryRunAll)...)
|
||||
return c.inner.Create(ctx, obj, append(opts, client.DryRunAll)...)
|
||||
}
|
||||
|
||||
func (c *dryRunClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error {
|
||||
return c.inner.Update(ctx, obj, append(opts, ctrlclient.DryRunAll)...)
|
||||
return c.inner.Update(ctx, obj, append(opts, client.DryRunAll)...)
|
||||
}
|
||||
|
||||
func (c *dryRunClient) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error {
|
||||
return c.inner.Delete(ctx, obj, append(opts, ctrlclient.DryRunAll)...)
|
||||
return c.inner.Delete(ctx, obj, append(opts, client.DryRunAll)...)
|
||||
}
|
||||
|
||||
func (c *dryRunClient) Get(ctx context.Context, key types.NamespacedName, obj client.Object, opts ...client.GetOption) error {
|
||||
|
@ -41,13 +38,13 @@ func (c *dryRunClient) List(ctx context.Context, list client.ObjectList, opts ..
|
|||
}
|
||||
|
||||
func (c *dryRunClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
return c.inner.Patch(ctx, obj, patch, append(opts, ctrlclient.DryRunAll)...)
|
||||
return c.inner.Patch(ctx, obj, patch, append(opts, client.DryRunAll)...)
|
||||
}
|
||||
|
||||
func (c *dryRunClient) RESTMapper() meta.RESTMapper {
|
||||
return c.inner.RESTMapper()
|
||||
}
|
||||
|
||||
func New(inner Client) Client {
|
||||
func DryRun(inner Client) Client {
|
||||
return &dryRunClient{inner: inner}
|
||||
}
|
|
@ -1,20 +1,20 @@
|
|||
package dryrun
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/client"
|
||||
tclient "github.com/kyverno/chainsaw/pkg/client/testing"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
func TestDryRun(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
inner Client
|
||||
|
@ -28,7 +28,7 @@ func TestNew(t *testing.T) {
|
|||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := New(tt.inner)
|
||||
got := DryRun(tt.inner)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
|
@ -61,28 +61,28 @@ func Test_dryRunClient_Create(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
inner := &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
CreateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.CreateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
CreateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
UpdateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.UpdateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
UpdateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
DeleteFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
ListFn: func(ctx context.Context, call int, list client.ObjectList, opts ...client.ListOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
ListFn: func(ctx context.Context, call int, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
PatchFn: func(ctx context.Context, call int, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
PatchFn: func(ctx context.Context, call int, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
IsObjectNamespacedFn: func(call int, obj runtime.Object) (bool, error) {
|
||||
|
@ -130,28 +130,28 @@ func Test_dryRunClient_Update(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
inner := &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
CreateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.CreateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
CreateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
UpdateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.UpdateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
UpdateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
DeleteFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
ListFn: func(ctx context.Context, call int, list client.ObjectList, opts ...client.ListOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
ListFn: func(ctx context.Context, call int, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
PatchFn: func(ctx context.Context, call int, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
PatchFn: func(ctx context.Context, call int, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
IsObjectNamespacedFn: func(call int, obj runtime.Object) (bool, error) {
|
||||
|
@ -199,28 +199,28 @@ func Test_dryRunClient_Delete(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
inner := &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
CreateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.CreateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
CreateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
UpdateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.UpdateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
UpdateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
DeleteFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
ListFn: func(ctx context.Context, call int, list client.ObjectList, opts ...client.ListOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
ListFn: func(ctx context.Context, call int, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
PatchFn: func(ctx context.Context, call int, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
PatchFn: func(ctx context.Context, call int, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
IsObjectNamespacedFn: func(call int, obj runtime.Object) (bool, error) {
|
||||
|
@ -268,28 +268,28 @@ func Test_dryRunClient_Get(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
inner := &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
CreateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.CreateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
CreateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
UpdateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.UpdateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
UpdateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
DeleteFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
ListFn: func(ctx context.Context, call int, list client.ObjectList, opts ...client.ListOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
ListFn: func(ctx context.Context, call int, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
PatchFn: func(ctx context.Context, call int, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
PatchFn: func(ctx context.Context, call int, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
IsObjectNamespacedFn: func(call int, obj runtime.Object) (bool, error) {
|
||||
|
@ -337,28 +337,28 @@ func Test_dryRunClient_List(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
inner := &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
CreateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.CreateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
CreateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
UpdateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.UpdateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
UpdateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
DeleteFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
ListFn: func(ctx context.Context, call int, list client.ObjectList, opts ...client.ListOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
ListFn: func(ctx context.Context, call int, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
PatchFn: func(ctx context.Context, call int, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
PatchFn: func(ctx context.Context, call int, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
IsObjectNamespacedFn: func(call int, obj runtime.Object) (bool, error) {
|
||||
|
@ -406,28 +406,28 @@ func Test_dryRunClient_Patch(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
inner := &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
CreateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.CreateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
CreateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
UpdateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.UpdateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
UpdateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
DeleteFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
ListFn: func(ctx context.Context, call int, list client.ObjectList, opts ...client.ListOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
ListFn: func(ctx context.Context, call int, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
PatchFn: func(ctx context.Context, call int, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
PatchFn: func(ctx context.Context, call int, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
IsObjectNamespacedFn: func(call int, obj runtime.Object) (bool, error) {
|
||||
|
@ -484,28 +484,28 @@ func Test_dryRunClient_IsObjectNamespaced(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
inner := &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
CreateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.CreateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
CreateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
UpdateFn: func(ctx context.Context, call int, obj client.Object, opts ...client.UpdateOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
UpdateFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
DeleteFn: func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
DeleteFn: func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
ListFn: func(ctx context.Context, call int, list client.ObjectList, opts ...client.ListOption) error {
|
||||
assert.NotContains(t, opts, ctrlclient.DryRunAll)
|
||||
ListFn: func(ctx context.Context, call int, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error {
|
||||
assert.NotContains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
PatchFn: func(ctx context.Context, call int, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
assert.Contains(t, opts, ctrlclient.DryRunAll)
|
||||
PatchFn: func(ctx context.Context, call int, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error {
|
||||
assert.Contains(t, opts, client.DryRunAll)
|
||||
return wantErr()
|
||||
},
|
||||
IsObjectNamespacedFn: func(call int, obj runtime.Object) (bool, error) {
|
|
@ -0,0 +1,36 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kyverno/pkg/ext/output/color"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func ObjectKey(obj metav1.Object) ctrlclient.ObjectKey {
|
||||
return ctrlclient.ObjectKey{
|
||||
Name: obj.GetName(),
|
||||
Namespace: obj.GetNamespace(),
|
||||
}
|
||||
}
|
||||
|
||||
func Name(key ctrlclient.ObjectKey) string {
|
||||
return ColouredName(key, nil)
|
||||
}
|
||||
|
||||
func ColouredName(key ctrlclient.ObjectKey, color *color.Color) string {
|
||||
sprint := fmt.Sprint
|
||||
if color != nil {
|
||||
sprint = color.Sprint
|
||||
}
|
||||
name := key.Name
|
||||
if name == "" {
|
||||
name = "*"
|
||||
}
|
||||
name = sprint(name)
|
||||
if key.Namespace != "" {
|
||||
name = sprint(key.Namespace) + "/" + name
|
||||
}
|
||||
return name
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/stretchr/testify/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func TestObjectKey(t *testing.T) {
|
||||
obj := &metav1.ObjectMeta{
|
||||
Name: "test-name",
|
||||
Namespace: "test-namespace",
|
||||
}
|
||||
|
||||
key := ObjectKey(obj)
|
||||
assert.Equal(t, "test-name", key.Name)
|
||||
assert.Equal(t, "test-namespace", key.Namespace)
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
key := ctrlclient.ObjectKey{Name: "test-name"}
|
||||
name := Name(key)
|
||||
assert.Equal(t, "test-name", name)
|
||||
|
||||
key.Namespace = "test-namespace"
|
||||
name = Name(key)
|
||||
assert.Equal(t, "test-namespace/test-name", name)
|
||||
|
||||
key = ctrlclient.ObjectKey{}
|
||||
name = Name(key)
|
||||
assert.Equal(t, "*", name)
|
||||
}
|
||||
|
||||
func TestColouredName(t *testing.T) {
|
||||
disabled := color.New(color.FgBlue)
|
||||
disabled.DisableColor()
|
||||
enabled := color.New(color.FgBlue)
|
||||
enabled.EnableColor()
|
||||
tests := []struct {
|
||||
name string
|
||||
key ctrlclient.ObjectKey
|
||||
color *color.Color
|
||||
want string
|
||||
}{{
|
||||
name: "empty",
|
||||
key: ctrlclient.ObjectKey{},
|
||||
color: nil,
|
||||
want: "*",
|
||||
}, {
|
||||
name: "name only",
|
||||
key: ctrlclient.ObjectKey{Name: "test-name"},
|
||||
color: nil,
|
||||
want: "test-name",
|
||||
}, {
|
||||
name: "name and namespace",
|
||||
key: ctrlclient.ObjectKey{Name: "test-name", Namespace: "test-namespace"},
|
||||
color: nil,
|
||||
want: "test-namespace/test-name",
|
||||
}, {
|
||||
name: "empty",
|
||||
key: ctrlclient.ObjectKey{},
|
||||
color: disabled,
|
||||
want: "*",
|
||||
}, {
|
||||
name: "name only",
|
||||
key: ctrlclient.ObjectKey{Name: "test-name"},
|
||||
color: disabled,
|
||||
want: "test-name",
|
||||
}, {
|
||||
name: "name and namespace",
|
||||
key: ctrlclient.ObjectKey{Name: "test-name", Namespace: "test-namespace"},
|
||||
color: disabled,
|
||||
want: "test-namespace/test-name",
|
||||
}, {
|
||||
name: "empty",
|
||||
key: ctrlclient.ObjectKey{},
|
||||
color: enabled,
|
||||
want: "\x1b[34m*\x1b[0m",
|
||||
}, {
|
||||
name: "name only",
|
||||
key: ctrlclient.ObjectKey{Name: "test-name"},
|
||||
color: enabled,
|
||||
want: "\x1b[34mtest-name\x1b[0m",
|
||||
}, {
|
||||
name: "name and namespace",
|
||||
key: ctrlclient.ObjectKey{Name: "test-name", Namespace: "test-namespace"},
|
||||
color: enabled,
|
||||
want: "\x1b[34mtest-namespace\x1b[0m/\x1b[34mtest-name\x1b[0m",
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := ColouredName(tt.key, tt.color)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package kube
|
||||
package client
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
@ -16,3 +16,7 @@ func Namespace(name string) corev1.Namespace {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
func PetNamespace() corev1.Namespace {
|
||||
return Namespace(Pet())
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package kube
|
||||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -10,7 +10,14 @@ import (
|
|||
func TestNamespace(t *testing.T) {
|
||||
expectedName := "testNamespace"
|
||||
ns := Namespace(expectedName)
|
||||
|
||||
assert.Equal(t, corev1.SchemeGroupVersion.String(), ns.APIVersion)
|
||||
assert.Equal(t, "Namespace", ns.Kind)
|
||||
assert.Equal(t, expectedName, ns.Name)
|
||||
}
|
||||
|
||||
func TestPetNamespace(t *testing.T) {
|
||||
ns := PetNamespace()
|
||||
|
||||
assert.NotEmpty(t, ns.Name)
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func PatchObject(actual, expected runtime.Object) (runtime.Object, error) {
|
||||
if actual == nil || expected == nil {
|
||||
return nil, errors.New("actual and expected objects must not be nil")
|
||||
}
|
||||
actualMeta, err := meta.Accessor(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy := expected.DeepCopyObject()
|
||||
expectedMeta, err := meta.Accessor(copy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
expectedMeta.SetResourceVersion(actualMeta.GetResourceVersion())
|
||||
return copy, nil
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
truntime "k8s.io/apimachinery/pkg/runtime/testing"
|
||||
)
|
||||
|
||||
func TestPatchObject(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
actual runtime.Object
|
||||
expected runtime.Object
|
||||
want runtime.Object
|
||||
wantErr bool
|
||||
}{{
|
||||
name: "acutal nil",
|
||||
actual: nil,
|
||||
expected: &unstructured.Unstructured{},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "expected nil",
|
||||
actual: &unstructured.Unstructured{},
|
||||
expected: nil,
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "ok",
|
||||
actual: &unstructured.Unstructured{
|
||||
Object: map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]any{
|
||||
"name": "test-pod",
|
||||
"resourceVersion": "12345",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &unstructured.Unstructured{
|
||||
Object: map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]any{
|
||||
"name": "test-pod",
|
||||
},
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
want: &unstructured.Unstructured{
|
||||
Object: map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]any{
|
||||
"name": "test-pod",
|
||||
"resourceVersion": "12345",
|
||||
},
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
}, {
|
||||
name: "actual not meta",
|
||||
actual: &truntime.InternalSimple{},
|
||||
expected: &unstructured.Unstructured{},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "expected not meta",
|
||||
actual: &unstructured.Unstructured{},
|
||||
expected: &truntime.InternalSimple{},
|
||||
wantErr: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := PatchObject(tt.actual, tt.expected)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
petname "github.com/dustinkirkland/golang-petname"
|
||||
)
|
||||
|
||||
func Pet() string {
|
||||
return fmt.Sprintf("chainsaw-%s", petname.Generate(2, "-"))
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package simple
|
||||
|
||||
import (
|
||||
"github.com/kyverno/chainsaw/pkg/client"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/rest"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func New(cfg *rest.Config) (client.Client, error) {
|
||||
var opts ctrlclient.Options
|
||||
client, err := ctrlclient.New(cfg, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ctrlclient.WithFieldValidation(client, metav1.FieldValidationStrict), nil
|
||||
}
|
|
@ -5,48 +5,48 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
client "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// TODO: not thread safe
|
||||
type FakeClient struct {
|
||||
GetFn func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error
|
||||
CreateFn func(ctx context.Context, call int, obj client.Object, opts ...client.CreateOption) error
|
||||
UpdateFn func(ctx context.Context, call int, obj client.Object, opts ...client.UpdateOption) error
|
||||
DeleteFn func(ctx context.Context, call int, obj client.Object, opts ...client.DeleteOption) error
|
||||
ListFn func(ctx context.Context, call int, list client.ObjectList, opts ...client.ListOption) error
|
||||
PatchFn func(ctx context.Context, call int, obj client.Object, patch client.Patch, opts ...client.PatchOption) error
|
||||
GetFn func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error
|
||||
CreateFn func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error
|
||||
UpdateFn func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error
|
||||
DeleteFn func(ctx context.Context, call int, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error
|
||||
ListFn func(ctx context.Context, call int, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error
|
||||
PatchFn func(ctx context.Context, call int, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error
|
||||
IsObjectNamespacedFn func(call int, obj runtime.Object) (bool, error)
|
||||
RESTMapperFn func(call int) meta.RESTMapper
|
||||
numCalls int
|
||||
}
|
||||
|
||||
func (c *FakeClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
func (c *FakeClient) Get(ctx context.Context, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
defer func() { c.numCalls++ }()
|
||||
return c.GetFn(ctx, c.numCalls, key, obj, opts...)
|
||||
}
|
||||
|
||||
func (c *FakeClient) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error {
|
||||
func (c *FakeClient) List(ctx context.Context, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error {
|
||||
defer func() { c.numCalls++ }()
|
||||
return c.ListFn(ctx, c.numCalls, list, opts...)
|
||||
}
|
||||
|
||||
func (c *FakeClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {
|
||||
func (c *FakeClient) Create(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error {
|
||||
defer func() { c.numCalls++ }()
|
||||
return c.CreateFn(ctx, c.numCalls, obj, opts...)
|
||||
}
|
||||
|
||||
func (c *FakeClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error {
|
||||
func (c *FakeClient) Update(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error {
|
||||
defer func() { c.numCalls++ }()
|
||||
return c.UpdateFn(ctx, c.numCalls, obj, opts...)
|
||||
}
|
||||
|
||||
func (c *FakeClient) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error {
|
||||
func (c *FakeClient) Delete(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error {
|
||||
defer func() { c.numCalls++ }()
|
||||
return c.DeleteFn(ctx, c.numCalls, obj, opts...)
|
||||
}
|
||||
|
||||
func (c *FakeClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
func (c *FakeClient) Patch(ctx context.Context, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error {
|
||||
defer func() { c.numCalls++ }()
|
||||
return c.PatchFn(ctx, c.numCalls, obj, patch, opts...)
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
type (
|
||||
Object = ctrlclient.Object
|
||||
ObjectKey = ctrlclient.ObjectKey
|
||||
ObjectList = ctrlclient.ObjectList
|
||||
Patch = ctrlclient.Patch
|
||||
GetOption = ctrlclient.GetOption
|
||||
ListOption = ctrlclient.ListOption
|
||||
CreateOption = ctrlclient.CreateOption
|
||||
UpdateOption = ctrlclient.UpdateOption
|
||||
DeleteOption = ctrlclient.DeleteOption
|
||||
PatchOption = ctrlclient.PatchOption
|
||||
InNamespace = ctrlclient.InNamespace
|
||||
PropagationPolicy = ctrlclient.PropagationPolicy
|
||||
MatchingLabels = ctrlclient.MatchingLabels
|
||||
)
|
||||
|
||||
var RawPatch = ctrlclient.RawPatch
|
|
@ -1,4 +1,4 @@
|
|||
package kube
|
||||
package client
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
@ -1,4 +1,4 @@
|
|||
package kube
|
||||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -1,74 +0,0 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/kyverno/pkg/ext/output/color"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
const PollInterval = 50 * time.Millisecond
|
||||
|
||||
func Key(obj metav1.Object) ObjectKey {
|
||||
return ObjectKey{
|
||||
Name: obj.GetName(),
|
||||
Namespace: obj.GetNamespace(),
|
||||
}
|
||||
}
|
||||
|
||||
func Name(key ObjectKey) string {
|
||||
return ColouredName(key, nil)
|
||||
}
|
||||
|
||||
func ColouredName(key ObjectKey, color *color.Color) string {
|
||||
sprint := fmt.Sprint
|
||||
if color != nil {
|
||||
sprint = color.Sprint
|
||||
}
|
||||
name := key.Name
|
||||
if name == "" {
|
||||
name = "*"
|
||||
}
|
||||
name = sprint(name)
|
||||
if key.Namespace != "" {
|
||||
name = sprint(key.Namespace) + "/" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func PatchObject(actual, expected runtime.Object) (runtime.Object, error) {
|
||||
if actual == nil || expected == nil {
|
||||
return nil, errors.New("actual and expected objects must not be nil")
|
||||
}
|
||||
actualMeta, err := meta.Accessor(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy := expected.DeepCopyObject()
|
||||
expectedMeta, err := meta.Accessor(copy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
expectedMeta.SetResourceVersion(actualMeta.GetResourceVersion())
|
||||
return copy, nil
|
||||
}
|
||||
|
||||
func WaitForDeletion(ctx context.Context, client Client, object Object) error {
|
||||
key := Key(object)
|
||||
return wait.PollUntilContextCancel(ctx, PollInterval, true, func(ctx context.Context) (bool, error) {
|
||||
if err := client.Get(ctx, key, object); err != nil {
|
||||
if kerrors.IsNotFound(err) {
|
||||
return true, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
}
|
|
@ -1,235 +0,0 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
tclient "github.com/kyverno/chainsaw/pkg/client/testing"
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kerror "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
truntime "k8s.io/apimachinery/pkg/runtime/testing"
|
||||
)
|
||||
|
||||
func TestObjectKey(t *testing.T) {
|
||||
obj := &metav1.ObjectMeta{
|
||||
Name: "test-name",
|
||||
Namespace: "test-namespace",
|
||||
}
|
||||
|
||||
key := Key(obj)
|
||||
assert.Equal(t, "test-name", key.Name)
|
||||
assert.Equal(t, "test-namespace", key.Namespace)
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
key := ObjectKey{Name: "test-name"}
|
||||
name := Name(key)
|
||||
assert.Equal(t, "test-name", name)
|
||||
|
||||
key.Namespace = "test-namespace"
|
||||
name = Name(key)
|
||||
assert.Equal(t, "test-namespace/test-name", name)
|
||||
|
||||
key = ObjectKey{}
|
||||
name = Name(key)
|
||||
assert.Equal(t, "*", name)
|
||||
}
|
||||
|
||||
func TestColouredName(t *testing.T) {
|
||||
disabled := color.New(color.FgBlue)
|
||||
disabled.DisableColor()
|
||||
enabled := color.New(color.FgBlue)
|
||||
enabled.EnableColor()
|
||||
tests := []struct {
|
||||
name string
|
||||
key ObjectKey
|
||||
color *color.Color
|
||||
want string
|
||||
}{{
|
||||
name: "empty",
|
||||
key: ObjectKey{},
|
||||
color: nil,
|
||||
want: "*",
|
||||
}, {
|
||||
name: "name only",
|
||||
key: ObjectKey{Name: "test-name"},
|
||||
color: nil,
|
||||
want: "test-name",
|
||||
}, {
|
||||
name: "name and namespace",
|
||||
key: ObjectKey{Name: "test-name", Namespace: "test-namespace"},
|
||||
color: nil,
|
||||
want: "test-namespace/test-name",
|
||||
}, {
|
||||
name: "empty",
|
||||
key: ObjectKey{},
|
||||
color: disabled,
|
||||
want: "*",
|
||||
}, {
|
||||
name: "name only",
|
||||
key: ObjectKey{Name: "test-name"},
|
||||
color: disabled,
|
||||
want: "test-name",
|
||||
}, {
|
||||
name: "name and namespace",
|
||||
key: ObjectKey{Name: "test-name", Namespace: "test-namespace"},
|
||||
color: disabled,
|
||||
want: "test-namespace/test-name",
|
||||
}, {
|
||||
name: "empty",
|
||||
key: ObjectKey{},
|
||||
color: enabled,
|
||||
want: "\x1b[34m*\x1b[0m",
|
||||
}, {
|
||||
name: "name only",
|
||||
key: ObjectKey{Name: "test-name"},
|
||||
color: enabled,
|
||||
want: "\x1b[34mtest-name\x1b[0m",
|
||||
}, {
|
||||
name: "name and namespace",
|
||||
key: ObjectKey{Name: "test-name", Namespace: "test-namespace"},
|
||||
color: enabled,
|
||||
want: "\x1b[34mtest-namespace\x1b[0m/\x1b[34mtest-name\x1b[0m",
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := ColouredName(tt.key, tt.color)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatchObject(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
actual runtime.Object
|
||||
expected runtime.Object
|
||||
want runtime.Object
|
||||
wantErr bool
|
||||
}{{
|
||||
name: "acutal nil",
|
||||
actual: nil,
|
||||
expected: &unstructured.Unstructured{},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "expected nil",
|
||||
actual: &unstructured.Unstructured{},
|
||||
expected: nil,
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "ok",
|
||||
actual: &unstructured.Unstructured{
|
||||
Object: map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]any{
|
||||
"name": "test-pod",
|
||||
"resourceVersion": "12345",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &unstructured.Unstructured{
|
||||
Object: map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]any{
|
||||
"name": "test-pod",
|
||||
},
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
want: &unstructured.Unstructured{
|
||||
Object: map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]any{
|
||||
"name": "test-pod",
|
||||
"resourceVersion": "12345",
|
||||
},
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
}, {
|
||||
name: "actual not meta",
|
||||
actual: &truntime.InternalSimple{},
|
||||
expected: &unstructured.Unstructured{},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "expected not meta",
|
||||
actual: &unstructured.Unstructured{},
|
||||
expected: &truntime.InternalSimple{},
|
||||
wantErr: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := PatchObject(tt.actual, tt.expected)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWaitForDeletion(t *testing.T) {
|
||||
obj := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
object Object
|
||||
client Client
|
||||
wantErr bool
|
||||
}{{
|
||||
name: "ok",
|
||||
object: obj,
|
||||
client: &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key ObjectKey, obj Object, opts ...GetOption) error {
|
||||
return kerror.NewNotFound(corev1.Resource("namespace"), "foo")
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
}, {
|
||||
name: "error",
|
||||
object: obj,
|
||||
client: &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key ObjectKey, obj Object, opts ...GetOption) error {
|
||||
return errors.New("dummy")
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "timeout",
|
||||
object: obj,
|
||||
client: &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key ObjectKey, obj Object, opts ...GetOption) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Second)
|
||||
defer cancel()
|
||||
err := WaitForDeletion(ctx, tt.client, tt.object)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -6,15 +6,13 @@ import (
|
|||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/apis"
|
||||
"github.com/kyverno/chainsaw/pkg/client"
|
||||
"github.com/kyverno/chainsaw/pkg/client/simple"
|
||||
"github.com/kyverno/chainsaw/pkg/apis/v1alpha1"
|
||||
ctrlClient "github.com/kyverno/chainsaw/pkg/client"
|
||||
tclient "github.com/kyverno/chainsaw/pkg/client/testing"
|
||||
engineclient "github.com/kyverno/chainsaw/pkg/engine/client"
|
||||
nspacer "github.com/kyverno/chainsaw/pkg/engine/namespacer"
|
||||
opassert "github.com/kyverno/chainsaw/pkg/engine/operations/assert"
|
||||
"github.com/kyverno/chainsaw/pkg/loaders/config"
|
||||
"github.com/kyverno/chainsaw/pkg/loaders/resource"
|
||||
runnerclient "github.com/kyverno/chainsaw/pkg/runner/client"
|
||||
nspacer "github.com/kyverno/chainsaw/pkg/runner/namespacer"
|
||||
opassert "github.com/kyverno/chainsaw/pkg/runner/operations/assert"
|
||||
restutils "github.com/kyverno/chainsaw/pkg/utils/rest"
|
||||
"github.com/kyverno/pkg/ext/output/color"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -48,13 +46,9 @@ func Command() *cobra.Command {
|
|||
return runE(opts, cmd, nil, nil)
|
||||
},
|
||||
}
|
||||
config, err := config.DefaultConfiguration()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cmd.Flags().StringVarP(&opts.assertPath, "file", "f", "", "Path to the file to assert or '-' to read from stdin")
|
||||
cmd.Flags().StringVarP(&opts.resourcePath, "resource", "r", "", "Path to the file containing the resource")
|
||||
cmd.Flags().DurationVar(&opts.timeout.Duration, "timeout", config.Spec.Timeouts.Assert.Duration, "The assert timeout to use")
|
||||
cmd.Flags().DurationVar(&opts.timeout.Duration, "timeout", v1alpha1.DefaultAssertTimeout, "The assert timeout to use")
|
||||
cmd.Flags().StringVar(&opts.namespace, "namespace", "default", "Namespace to use")
|
||||
cmd.Flags().BoolVar(&opts.noColor, "no-color", false, "Removes output colors")
|
||||
cmd.Flags().BoolVar(&opts.noColor, "clustered", false, "Defines if the resource is clustered (only applies when resource is loaded from a file)")
|
||||
|
@ -71,7 +65,7 @@ func preRunE(opts *options, _ *cobra.Command, args []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func runE(opts options, cmd *cobra.Command, client client.Client, namespacer nspacer.Namespacer) error {
|
||||
func runE(opts options, cmd *cobra.Command, client ctrlClient.Client, namespacer nspacer.Namespacer) error {
|
||||
color.Init(opts.noColor, true)
|
||||
out := cmd.OutOrStdout()
|
||||
var assertions []unstructured.Unstructured
|
||||
|
@ -119,14 +113,14 @@ func runE(opts options, cmd *cobra.Command, client client.Client, namespacer nsp
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newClient, err := simple.New(cfg)
|
||||
newClient, err := ctrlClient.New(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client = engineclient.New(newClient)
|
||||
client = runnerclient.New(newClient)
|
||||
}
|
||||
if namespacer == nil {
|
||||
namespacer = nspacer.New(opts.namespace)
|
||||
namespacer = nspacer.New(client, opts.namespace)
|
||||
}
|
||||
for _, assertion := range assertions {
|
||||
if err := assert(opts, client, assertion, namespacer); err != nil {
|
||||
|
@ -137,14 +131,10 @@ func runE(opts options, cmd *cobra.Command, client client.Client, namespacer nsp
|
|||
return nil
|
||||
}
|
||||
|
||||
func assert(opts options, client client.Client, resource unstructured.Unstructured, namespacer nspacer.Namespacer) error {
|
||||
ctx := context.Background()
|
||||
if opts.timeout.Duration != 0 {
|
||||
_ctx, cancel := context.WithTimeout(ctx, opts.timeout.Duration)
|
||||
defer cancel()
|
||||
ctx = _ctx
|
||||
}
|
||||
op := opassert.New(apis.DefaultCompilers, client, resource, namespacer, false)
|
||||
func assert(opts options, client ctrlClient.Client, resource unstructured.Unstructured, namespacer nspacer.Namespacer) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), opts.timeout.Duration)
|
||||
defer cancel()
|
||||
op := opassert.New(client, resource, namespacer, false)
|
||||
_, err := op.Exec(ctx, nil)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -3,30 +3,23 @@ package assert
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/client"
|
||||
tclient "github.com/kyverno/chainsaw/pkg/client/testing"
|
||||
"github.com/kyverno/chainsaw/pkg/commands/root"
|
||||
fakeNamespacer "github.com/kyverno/chainsaw/pkg/engine/namespacer/testing"
|
||||
fakeNamespacer "github.com/kyverno/chainsaw/pkg/runner/namespacer/testing"
|
||||
"github.com/kyverno/chainsaw/pkg/testing"
|
||||
"github.com/spf13/cobra"
|
||||
testify "github.com/stretchr/testify/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
type errReader struct{}
|
||||
|
||||
func (e *errReader) Read(p []byte) (n int, err error) {
|
||||
return 0, errors.New("error reading from stdin")
|
||||
}
|
||||
|
||||
func Test_Execute(t *testing.T) {
|
||||
basePath := path.Join("..", "..", "..", "testdata", "commands", "assert")
|
||||
tests := []struct {
|
||||
|
@ -157,7 +150,7 @@ func Test_runE(t *testing.T) {
|
|||
timeout: metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
client: &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
obj.(*unstructured.Unstructured).Object = map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
|
@ -172,7 +165,7 @@ func Test_runE(t *testing.T) {
|
|||
},
|
||||
},
|
||||
nspacer: &fakeNamespacer.FakeNamespacer{
|
||||
ApplyFn: func(call int, client client.Client, obj client.Object) error {
|
||||
ApplyFn: func(obj ctrlclient.Object, call int) error {
|
||||
return nil
|
||||
},
|
||||
GetNamespaceFn: func(call int) string {
|
||||
|
@ -196,7 +189,7 @@ func Test_runE(t *testing.T) {
|
|||
timeout: metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
client: &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
obj.(*unstructured.Unstructured).Object = map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
|
@ -211,7 +204,7 @@ func Test_runE(t *testing.T) {
|
|||
},
|
||||
},
|
||||
nspacer: &fakeNamespacer.FakeNamespacer{
|
||||
ApplyFn: func(call int, client client.Client, obj client.Object) error {
|
||||
ApplyFn: func(obj ctrlclient.Object, call int) error {
|
||||
return nil
|
||||
},
|
||||
GetNamespaceFn: func(call int) string {
|
||||
|
@ -222,7 +215,7 @@ func Test_runE(t *testing.T) {
|
|||
"------------------------\n" +
|
||||
"v1/ConfigMap/quick-start\n" +
|
||||
"------------------------\n" +
|
||||
"* data.foo: Required value: field not found in the input object\n\n" +
|
||||
"* data.foo: Invalid value: \"null\": Expected value: \"bar\"\n\n" +
|
||||
"--- expected\n" +
|
||||
"+++ actual\n" +
|
||||
"@@ -1,6 +1,5 @@\n" +
|
||||
|
@ -250,7 +243,7 @@ func Test_runE(t *testing.T) {
|
|||
timeout: metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
client: &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
obj.(*unstructured.Unstructured).Object = map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
|
@ -265,7 +258,7 @@ func Test_runE(t *testing.T) {
|
|||
},
|
||||
},
|
||||
nspacer: &fakeNamespacer.FakeNamespacer{
|
||||
ApplyFn: func(call int, client client.Client, obj client.Object) error {
|
||||
ApplyFn: func(obj ctrlclient.Object, call int) error {
|
||||
return nil
|
||||
},
|
||||
GetNamespaceFn: func(call int) string {
|
||||
|
@ -297,7 +290,7 @@ data:
|
|||
timeout: metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
client: &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
obj.(*unstructured.Unstructured).Object = map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
|
@ -312,7 +305,7 @@ data:
|
|||
},
|
||||
},
|
||||
nspacer: &fakeNamespacer.FakeNamespacer{
|
||||
ApplyFn: func(call int, client client.Client, obj client.Object) error {
|
||||
ApplyFn: func(obj ctrlclient.Object, call int) error {
|
||||
return nil
|
||||
},
|
||||
GetNamespaceFn: func(call int) string {
|
||||
|
@ -327,7 +320,7 @@ data:
|
|||
cmd.Args = cobra.RangeArgs(0, 1)
|
||||
cmd.SilenceUsage = true
|
||||
cmd.SetOut(bytes.NewBufferString(""))
|
||||
cmd.SetIn(&errReader{})
|
||||
cmd.SetIn(&testing.ErrReader{})
|
||||
return cmd
|
||||
},
|
||||
opts: options{
|
||||
|
@ -337,7 +330,7 @@ data:
|
|||
timeout: metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
client: &tclient.FakeClient{
|
||||
GetFn: func(ctx context.Context, call int, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
|
||||
GetFn: func(ctx context.Context, call int, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
|
||||
obj.(*unstructured.Unstructured).Object = map[string]any{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
|
@ -352,7 +345,7 @@ data:
|
|||
},
|
||||
},
|
||||
nspacer: &fakeNamespacer.FakeNamespacer{
|
||||
ApplyFn: func(call int, client client.Client, obj client.Object) error {
|
||||
ApplyFn: func(obj ctrlclient.Object, call int) error {
|
||||
return nil
|
||||
},
|
||||
GetNamespaceFn: func(call int) string {
|
||||
|
|
|
@ -108,7 +108,7 @@ wait
|
|||
{{- with .Test.Spec.Steps }}
|
||||
|
||||
| # | Name | Bindings | Try | Catch | Finally | Cleanup |
|
||||
|:-:|---|:-:|:-:|:-:|:-:|:-:|
|
||||
|:-:|---|:-:|:-:|:-:|:-:|
|
||||
{{- range $i, $step := . }}
|
||||
{{- $name := default (print "step-" (add $i 1)) $step.Name }}
|
||||
| {{ add $i 1 }} | [{{ $name }}](#step-{{ $name }}) | {{ len $step.Bindings }} | {{ len $step.Try }} | {{ add (len $step.Catch) (len $test.Test.Spec.Catch) }} | {{ len $step.Finally }} | {{ len $step.Cleanup }} |
|
||||
|
|
|
@ -19,7 +19,7 @@ func websitePrepender(filename string) string {
|
|||
now := time.Now().Format(time.RFC3339)
|
||||
name := filepath.Base(filename)
|
||||
base := strings.TrimSuffix(name, path.Ext(name))
|
||||
return fmt.Sprintf(fmTemplate, now, strings.ReplaceAll(base, "_", " "))
|
||||
return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1))
|
||||
}
|
||||
|
||||
func websiteLinkHandler(filename string) string {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/data"
|
||||
|
@ -26,16 +27,13 @@ func Command() *cobra.Command {
|
|||
return err
|
||||
}
|
||||
}
|
||||
schemasFs, err := data.Schemas()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
entries, err := fs.ReadDir(schemasFs, ".")
|
||||
schemasFs := data.Schemas()
|
||||
entries, err := fs.ReadDir(schemasFs, path.Join("schemas", "json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, entry := range entries {
|
||||
input, err := fs.ReadFile(schemasFs, entry.Name())
|
||||
input, err := fs.ReadFile(schemasFs, path.Join("schemas", "json", entry.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package lint
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -9,7 +8,6 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/xeipuuv/gojsonschema"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
func Command() *cobra.Command {
|
||||
|
@ -42,16 +40,16 @@ func Command() *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func lintInput(input []byte, kind string, format string, writer io.Writer) error {
|
||||
func lintInput(input []byte, schema string, format string, writer io.Writer) error {
|
||||
fmt.Fprintln(writer, "Processing input...")
|
||||
if err := lintSchema(input, kind, format, writer); err != nil {
|
||||
if err := lintSchema(input, schema, format, writer); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(writer, "The document is valid")
|
||||
return nil
|
||||
}
|
||||
|
||||
func lintSchema(input []byte, kind string, format string, writer io.Writer) error {
|
||||
func lintSchema(input []byte, schema string, format string, writer io.Writer) error {
|
||||
processor, err := getProcessor(format, input)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -60,15 +58,7 @@ func lintSchema(input []byte, kind string, format string, writer io.Writer) erro
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var unstructured map[string]any
|
||||
if err := json.Unmarshal(jsonInput, &unstructured); err != nil {
|
||||
return err
|
||||
}
|
||||
gv, err := schema.ParseGroupVersion(unstructured["apiVersion"].(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
goschema, err := getScheme(kind, gv.Version)
|
||||
goschema, err := getScheme(schema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -3,14 +3,26 @@ package lint
|
|||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"path"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/data"
|
||||
)
|
||||
|
||||
func getScheme(kind string, version string) ([]byte, error) {
|
||||
schemasFs, err := data.Schemas()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func getScheme(schema string) ([]byte, error) {
|
||||
switch schema {
|
||||
case "test":
|
||||
return getTestSchema()
|
||||
case "configuration":
|
||||
return getConfigurationSchema()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown schema: %s", schema)
|
||||
}
|
||||
return fs.ReadFile(schemasFs, fmt.Sprintf("%s-chainsaw-%s.json", kind, version))
|
||||
}
|
||||
|
||||
func getTestSchema() ([]byte, error) {
|
||||
return fs.ReadFile(data.Schemas(), path.Join("schemas", "json", "test-chainsaw-v1alpha1.json"))
|
||||
}
|
||||
|
||||
func getConfigurationSchema() ([]byte, error) {
|
||||
return fs.ReadFile(data.Schemas(), path.Join("schemas", "json", "configuration-chainsaw-v1alpha1.json"))
|
||||
}
|
||||
|
|
|
@ -118,16 +118,16 @@ func testSuite(in unstructured.Unstructured) (*v1alpha1.Configuration, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var timeouts v1alpha1.DefaultTimeouts
|
||||
var timeouts v1alpha1.Timeouts
|
||||
if from.Timeout != 0 {
|
||||
d := metav1.Duration{Duration: time.Second * time.Duration(from.Timeout)}
|
||||
timeouts = v1alpha1.DefaultTimeouts{
|
||||
Apply: d,
|
||||
Assert: d,
|
||||
Error: d,
|
||||
Delete: d,
|
||||
Cleanup: d,
|
||||
Exec: d,
|
||||
timeouts = v1alpha1.Timeouts{
|
||||
Apply: &d,
|
||||
Assert: &d,
|
||||
Error: &d,
|
||||
Delete: &d,
|
||||
Cleanup: &d,
|
||||
Exec: &d,
|
||||
}
|
||||
}
|
||||
to := &v1alpha1.Configuration{
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
|
@ -19,6 +18,7 @@ import (
|
|||
fsutils "github.com/kyverno/chainsaw/pkg/utils/fs"
|
||||
"github.com/kyverno/pkg/ext/resource/convert"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/maps"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/utils/ptr"
|
||||
|
@ -75,6 +75,8 @@ func processFolder(stdout io.Writer, stderr io.Writer, folder string, save, clea
|
|||
}
|
||||
if len(steps) != 0 {
|
||||
fmt.Fprintf(stderr, "Converting test %s ...\n", folder)
|
||||
keys := maps.Keys(steps)
|
||||
slices.Sort(keys)
|
||||
test := v1alpha1.Test{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: v1alpha1.SchemeGroupVersion.String(),
|
||||
|
@ -82,7 +84,7 @@ func processFolder(stdout io.Writer, stderr io.Writer, folder string, save, clea
|
|||
},
|
||||
}
|
||||
test.SetName(strings.ToLower(strings.ReplaceAll(filepath.Base(folder), "_", "-")))
|
||||
for _, key := range slices.Sorted(maps.Keys(steps)) {
|
||||
for _, key := range keys {
|
||||
step := v1alpha1.TestStep{
|
||||
Name: fmt.Sprintf("step-%s", key),
|
||||
}
|
||||
|
@ -151,11 +153,11 @@ func processStep(stderr io.Writer, step *v1alpha1.TestStep, s discovery.Step, fo
|
|||
}
|
||||
}
|
||||
if !containsKuttlResources {
|
||||
step.Try = append(step.Try, v1alpha1.Operation{
|
||||
step.TestStepSpec.Try = append(step.TestStepSpec.Try, v1alpha1.Operation{
|
||||
Apply: &v1alpha1.Apply{
|
||||
ActionResourceRef: v1alpha1.ActionResourceRef{
|
||||
FileRef: v1alpha1.FileRef{
|
||||
File: v1alpha1.Expression(file),
|
||||
File: file,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -193,11 +195,11 @@ func processStep(stderr io.Writer, step *v1alpha1.TestStep, s discovery.Step, fo
|
|||
return err
|
||||
}
|
||||
}
|
||||
step.Try = append(step.Try, v1alpha1.Operation{
|
||||
step.TestStepSpec.Try = append(step.TestStepSpec.Try, v1alpha1.Operation{
|
||||
Apply: &v1alpha1.Apply{
|
||||
ActionResourceRef: v1alpha1.ActionResourceRef{
|
||||
FileRef: v1alpha1.FileRef{
|
||||
File: v1alpha1.Expression(file),
|
||||
File: file,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -218,11 +220,11 @@ func processStep(stderr io.Writer, step *v1alpha1.TestStep, s discovery.Step, fo
|
|||
}
|
||||
}
|
||||
if !containsKuttlResources {
|
||||
step.Try = append(step.Try, v1alpha1.Operation{
|
||||
step.TestStepSpec.Try = append(step.TestStepSpec.Try, v1alpha1.Operation{
|
||||
Assert: &v1alpha1.Assert{
|
||||
ActionCheckRef: v1alpha1.ActionCheckRef{
|
||||
FileRef: v1alpha1.FileRef{
|
||||
File: v1alpha1.Expression(file),
|
||||
File: file,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -254,11 +256,11 @@ func processStep(stderr io.Writer, step *v1alpha1.TestStep, s discovery.Step, fo
|
|||
return err
|
||||
}
|
||||
}
|
||||
step.Try = append(step.Try, v1alpha1.Operation{
|
||||
step.TestStepSpec.Try = append(step.TestStepSpec.Try, v1alpha1.Operation{
|
||||
Assert: &v1alpha1.Assert{
|
||||
ActionCheckRef: v1alpha1.ActionCheckRef{
|
||||
FileRef: v1alpha1.FileRef{
|
||||
File: v1alpha1.Expression(file),
|
||||
File: file,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -279,11 +281,11 @@ func processStep(stderr io.Writer, step *v1alpha1.TestStep, s discovery.Step, fo
|
|||
}
|
||||
}
|
||||
if !containsKuttlResources {
|
||||
step.Try = append(step.Try, v1alpha1.Operation{
|
||||
step.TestStepSpec.Try = append(step.TestStepSpec.Try, v1alpha1.Operation{
|
||||
Error: &v1alpha1.Error{
|
||||
ActionCheckRef: v1alpha1.ActionCheckRef{
|
||||
FileRef: v1alpha1.FileRef{
|
||||
File: v1alpha1.Expression(file),
|
||||
File: file,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -315,11 +317,11 @@ func processStep(stderr io.Writer, step *v1alpha1.TestStep, s discovery.Step, fo
|
|||
return err
|
||||
}
|
||||
}
|
||||
step.Try = append(step.Try, v1alpha1.Operation{
|
||||
step.TestStepSpec.Try = append(step.TestStepSpec.Try, v1alpha1.Operation{
|
||||
Error: &v1alpha1.Error{
|
||||
ActionCheckRef: v1alpha1.ActionCheckRef{
|
||||
FileRef: v1alpha1.FileRef{
|
||||
File: v1alpha1.Expression(file),
|
||||
File: file,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -420,7 +422,7 @@ func testStep(to *v1alpha1.TestStepSpec, in unstructured.Unstructured) error {
|
|||
Apply: &v1alpha1.Apply{
|
||||
ActionResourceRef: v1alpha1.ActionResourceRef{
|
||||
FileRef: v1alpha1.FileRef{
|
||||
File: v1alpha1.Expression(operation),
|
||||
File: operation,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -431,7 +433,7 @@ func testStep(to *v1alpha1.TestStepSpec, in unstructured.Unstructured) error {
|
|||
Assert: &v1alpha1.Assert{
|
||||
ActionCheckRef: v1alpha1.ActionCheckRef{
|
||||
FileRef: v1alpha1.FileRef{
|
||||
File: v1alpha1.Expression(operation),
|
||||
File: operation,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -442,7 +444,7 @@ func testStep(to *v1alpha1.TestStepSpec, in unstructured.Unstructured) error {
|
|||
Error: &v1alpha1.Error{
|
||||
ActionCheckRef: v1alpha1.ActionCheckRef{
|
||||
FileRef: v1alpha1.FileRef{
|
||||
File: v1alpha1.Expression(operation),
|
||||
File: operation,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -453,12 +455,12 @@ func testStep(to *v1alpha1.TestStepSpec, in unstructured.Unstructured) error {
|
|||
Delete: &v1alpha1.Delete{
|
||||
Ref: &v1alpha1.ObjectReference{
|
||||
ObjectType: v1alpha1.ObjectType{
|
||||
APIVersion: v1alpha1.Expression(operation.APIVersion),
|
||||
Kind: v1alpha1.Expression(operation.Kind),
|
||||
APIVersion: operation.APIVersion,
|
||||
Kind: operation.Kind,
|
||||
},
|
||||
ObjectName: v1alpha1.ObjectName{
|
||||
Namespace: v1alpha1.Expression(operation.Namespace),
|
||||
Name: v1alpha1.Expression(operation.Name),
|
||||
Namespace: operation.Namespace,
|
||||
Name: operation.Name,
|
||||
},
|
||||
Labels: operation.Labels,
|
||||
},
|
||||
|
@ -504,12 +506,12 @@ func testAssert(to *v1alpha1.TestStepSpec, in unstructured.Unstructured) error {
|
|||
op := &v1alpha1.PodLogs{
|
||||
ActionObjectSelector: v1alpha1.ActionObjectSelector{
|
||||
ObjectName: v1alpha1.ObjectName{
|
||||
Name: v1alpha1.Expression(collector.Pod),
|
||||
Namespace: v1alpha1.Expression(collector.Namespace),
|
||||
Name: collector.Pod,
|
||||
Namespace: collector.Namespace,
|
||||
},
|
||||
Selector: v1alpha1.Expression(collector.Selector),
|
||||
Selector: collector.Selector,
|
||||
},
|
||||
Container: v1alpha1.Expression(collector.Container),
|
||||
Container: collector.Container,
|
||||
}
|
||||
if collector.Tail != 0 {
|
||||
op.Tail = ptr.To(collector.Tail)
|
||||
|
@ -529,10 +531,10 @@ func testAssert(to *v1alpha1.TestStepSpec, in unstructured.Unstructured) error {
|
|||
Events: &v1alpha1.Events{
|
||||
ActionObjectSelector: v1alpha1.ActionObjectSelector{
|
||||
ObjectName: v1alpha1.ObjectName{
|
||||
Name: v1alpha1.Expression(collector.Pod),
|
||||
Namespace: v1alpha1.Expression(collector.Namespace),
|
||||
Name: collector.Pod,
|
||||
Namespace: collector.Namespace,
|
||||
},
|
||||
Selector: v1alpha1.Expression(collector.Selector),
|
||||
Selector: collector.Selector,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package renovate
|
||||
|
||||
import (
|
||||
"github.com/kyverno/chainsaw/pkg/commands/renovate/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func Command() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "renovate",
|
||||
Short: "Upgrade Chainsaw resources",
|
||||
Args: cobra.NoArgs,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
return cmd.Help()
|
||||
},
|
||||
}
|
||||
cmd.AddCommand(
|
||||
config.Command(),
|
||||
)
|
||||
return cmd
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package renovate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/commands/root"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_Execute(t *testing.T) {
|
||||
basePath := "../../../testdata/commands/renovate"
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
wantErr bool
|
||||
out string
|
||||
}{{
|
||||
name: "help",
|
||||
args: []string{
|
||||
"renovate",
|
||||
"--help",
|
||||
},
|
||||
out: filepath.Join(basePath, "help.txt"),
|
||||
wantErr: false,
|
||||
}, {
|
||||
name: "renovate",
|
||||
args: []string{
|
||||
"renovate",
|
||||
},
|
||||
out: filepath.Join(basePath, "help.txt"),
|
||||
wantErr: false,
|
||||
}, {
|
||||
name: "unknow flag",
|
||||
args: []string{
|
||||
"renovate",
|
||||
"--foo",
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "unknow arg",
|
||||
args: []string{
|
||||
"renovate",
|
||||
"foo",
|
||||
},
|
||||
wantErr: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := root.Command()
|
||||
cmd.AddCommand(Command())
|
||||
assert.NotNil(t, cmd)
|
||||
cmd.SetArgs(tt.args)
|
||||
out := bytes.NewBufferString("")
|
||||
cmd.SetOut(out)
|
||||
err := cmd.Execute()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
actual, err := io.ReadAll(out)
|
||||
assert.NoError(t, err)
|
||||
if tt.out != "" {
|
||||
expected, err := os.ReadFile(tt.out)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, string(expected), string(actual))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"github.com/kyverno/chainsaw/pkg/apis/v1alpha2"
|
||||
"github.com/kyverno/chainsaw/pkg/loaders/config"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const schema = "# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/configuration-chainsaw-v1alpha2.json"
|
||||
|
||||
func Command() *cobra.Command {
|
||||
save := false
|
||||
cmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Upgrade Chainsaw configuration to the latest version",
|
||||
SilenceUsage: true,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return execute(
|
||||
cmd.OutOrStdout(),
|
||||
cmd.ErrOrStderr(),
|
||||
save,
|
||||
args[0],
|
||||
)
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolVar(&save, "save", false, "If set, converted files will be saved")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func execute(stdout io.Writer, stderr io.Writer, save bool, file string) error {
|
||||
c, err := loadConfig(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load configuration file %s: %w", file, err)
|
||||
}
|
||||
u, err := buildConfigPatch(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := yaml.Marshal(u)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal configuration patch: %w", err)
|
||||
}
|
||||
if save {
|
||||
fmt.Fprintf(stderr, "Saving file %s ...\n", file)
|
||||
f, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open file: %w", err)
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err := f.WriteString(schema + "\n"); err != nil {
|
||||
return fmt.Errorf("failed to write in file: %w", err)
|
||||
}
|
||||
if _, err := f.Write(data); err != nil {
|
||||
return fmt.Errorf("failed to write in file: %w", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintln(stdout, schema)
|
||||
fmt.Fprintln(stdout, string(data))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadConfig(file string) (*v1alpha2.Configuration, error) {
|
||||
return config.Load(file)
|
||||
}
|
||||
|
||||
func loadDefaultConfig() (*v1alpha2.Configuration, error) {
|
||||
return config.DefaultConfiguration()
|
||||
}
|
||||
|
||||
func buildConfigPatch(c *v1alpha2.Configuration) (*unstructured.Unstructured, error) {
|
||||
d, err := loadDefaultConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load default configuration: %w", err)
|
||||
}
|
||||
o, err := json.Marshal(d)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal default configuration: %w", err)
|
||||
}
|
||||
m, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal desired configuration: %w", err)
|
||||
}
|
||||
patch, err := jsonpatch.CreateMergePatch(o, m)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create patch from default to desired configuration: %w", err)
|
||||
}
|
||||
var i map[string]any
|
||||
if err := json.Unmarshal(patch, &i); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal configuration patch: %w", err)
|
||||
}
|
||||
u := unstructured.Unstructured{
|
||||
Object: i,
|
||||
}
|
||||
u.SetAPIVersion(v1alpha2.GroupVersion.String())
|
||||
u.SetKind("Configuration")
|
||||
u.SetName(c.Name)
|
||||
u.SetLabels(c.Labels)
|
||||
u.SetAnnotations(c.Annotations)
|
||||
return &u, nil
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/commands/root"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_Execute(t *testing.T) {
|
||||
basePath := "../../../../testdata/commands/renovate/config"
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
wantErr bool
|
||||
out string
|
||||
}{{
|
||||
name: "help",
|
||||
args: []string{
|
||||
"config",
|
||||
"--help",
|
||||
},
|
||||
out: filepath.Join(basePath, "help.txt"),
|
||||
wantErr: false,
|
||||
}, {
|
||||
name: "v1alpha1/default",
|
||||
args: []string{
|
||||
"config",
|
||||
"../../../../testdata/config/v1alpha1/default.yaml",
|
||||
},
|
||||
out: filepath.Join(basePath, "v1alpha1-default.txt"),
|
||||
wantErr: false,
|
||||
}, {
|
||||
name: "v1alpha1/custom",
|
||||
args: []string{
|
||||
"config",
|
||||
"../../../../testdata/config/v1alpha1/custom-config.yaml",
|
||||
},
|
||||
out: filepath.Join(basePath, "v1alpha1-custom.txt"),
|
||||
wantErr: false,
|
||||
// }, {
|
||||
// name: "renovate save",
|
||||
// args: []string{
|
||||
// "config",
|
||||
// "../../../../testdata/config/v1alpha1/default.yaml",
|
||||
// "--save",
|
||||
// },
|
||||
// out: filepath.Join(basePath, "out-save.txt"),
|
||||
// wantErr: false,
|
||||
}, {
|
||||
name: "unknow flag",
|
||||
args: []string{
|
||||
"config",
|
||||
"--foo",
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "unknown file",
|
||||
args: []string{
|
||||
"config",
|
||||
"../../../../testdata/config/unknown.yaml",
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "multiple file",
|
||||
args: []string{
|
||||
"config",
|
||||
"../../../../testdata/config/multiple.yaml",
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "invalid config",
|
||||
args: []string{
|
||||
"config",
|
||||
"../../../../testdata/config/v1alpha1/bad-catch.yaml",
|
||||
},
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "configmap",
|
||||
args: []string{
|
||||
"config",
|
||||
"../../../../testdata/config/configmap.yaml",
|
||||
},
|
||||
wantErr: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := root.Command()
|
||||
cmd.AddCommand(Command())
|
||||
assert.NotNil(t, cmd)
|
||||
cmd.SetArgs(tt.args)
|
||||
out := bytes.NewBufferString("")
|
||||
cmd.SetOut(out)
|
||||
err := cmd.Execute()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
actual, err := io.ReadAll(out)
|
||||
assert.NoError(t, err)
|
||||
if tt.out != "" {
|
||||
expected, err := os.ReadFile(tt.out)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, string(expected), string(actual))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/kyverno/chainsaw/pkg/commands/export"
|
||||
"github.com/kyverno/chainsaw/pkg/commands/lint"
|
||||
"github.com/kyverno/chainsaw/pkg/commands/migrate"
|
||||
"github.com/kyverno/chainsaw/pkg/commands/renovate"
|
||||
"github.com/kyverno/chainsaw/pkg/commands/root"
|
||||
"github.com/kyverno/chainsaw/pkg/commands/test"
|
||||
"github.com/kyverno/chainsaw/pkg/commands/version"
|
||||
|
@ -25,7 +24,6 @@ func RootCommand() *cobra.Command {
|
|||
export.Command(),
|
||||
lint.Command(),
|
||||
migrate.Command(),
|
||||
renovate.Command(),
|
||||
test.Command(),
|
||||
version.Command(),
|
||||
)
|
||||
|
|
|
@ -4,18 +4,20 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/kyverno/chainsaw/pkg/apis/v1alpha1"
|
||||
"github.com/kyverno/chainsaw/pkg/apis/v1alpha2"
|
||||
"github.com/kyverno/chainsaw/pkg/data"
|
||||
"github.com/kyverno/chainsaw/pkg/discovery"
|
||||
"github.com/kyverno/chainsaw/pkg/loaders/config"
|
||||
"github.com/kyverno/chainsaw/pkg/loaders/values"
|
||||
"github.com/kyverno/chainsaw/pkg/report"
|
||||
"github.com/kyverno/chainsaw/pkg/runner"
|
||||
enginecontext "github.com/kyverno/chainsaw/pkg/runner/context"
|
||||
runnerflags "github.com/kyverno/chainsaw/pkg/runner/flags"
|
||||
"github.com/kyverno/chainsaw/pkg/runner/failer"
|
||||
"github.com/kyverno/chainsaw/pkg/runner/template"
|
||||
flagutils "github.com/kyverno/chainsaw/pkg/utils/flag"
|
||||
fsutils "github.com/kyverno/chainsaw/pkg/utils/fs"
|
||||
restutils "github.com/kyverno/chainsaw/pkg/utils/rest"
|
||||
|
@ -42,7 +44,6 @@ type options struct {
|
|||
testDirs []string
|
||||
skipDelete bool
|
||||
template bool
|
||||
defaultCompiler string
|
||||
failFast bool
|
||||
parallel int
|
||||
repeatCount int
|
||||
|
@ -64,8 +65,6 @@ type options struct {
|
|||
values []string
|
||||
clusters []string
|
||||
remarshal bool
|
||||
shardIndex int
|
||||
shardCount int
|
||||
}
|
||||
|
||||
func Command() *cobra.Command {
|
||||
|
@ -77,29 +76,31 @@ func Command() *cobra.Command {
|
|||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
color.Init(options.noColor, true)
|
||||
clock := clock.RealClock{}
|
||||
stdOut := cmd.OutOrStdout()
|
||||
stdErr := cmd.ErrOrStderr()
|
||||
stdIn := cmd.InOrStdin()
|
||||
fmt.Fprintf(stdOut, "Version: %s\n", version.Version())
|
||||
out := cmd.OutOrStdout()
|
||||
fmt.Fprintf(out, "Version: %s\n", version.Version())
|
||||
var configuration v1alpha2.Configuration
|
||||
// if no config file was provided, give a chance to the default config name
|
||||
if options.config == "" {
|
||||
if _, err := os.Stat(config.DefaultFileName); err == nil {
|
||||
options.config = config.DefaultFileName
|
||||
fmt.Fprintf(stdOut, "No configuration provided but found default file: %s\n", options.config)
|
||||
fmt.Fprintf(out, "No configuration provided but found default file: %s\n", options.config)
|
||||
}
|
||||
}
|
||||
// try to load configuration file
|
||||
if options.config != "" {
|
||||
fmt.Fprintf(stdOut, "Loading config (%s)...\n", options.config)
|
||||
fmt.Fprintf(out, "Loading config (%s)...\n", options.config)
|
||||
config, err := config.Load(options.config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
configuration = *config
|
||||
} else {
|
||||
fmt.Fprintln(stdOut, "Loading default configuration...")
|
||||
config, err := config.DefaultConfiguration()
|
||||
fmt.Fprintln(out, "Loading default configuration...")
|
||||
bytes, err := fs.ReadFile(data.Config(), path.Join("config", "default.yaml"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config, err := config.LoadBytes(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -111,22 +112,22 @@ func Command() *cobra.Command {
|
|||
configuration.Spec.Discovery.TestFile = options.testFile
|
||||
}
|
||||
if flagutils.IsSet(flags, "apply-timeout") {
|
||||
configuration.Spec.Timeouts.Apply = options.applyTimeout
|
||||
configuration.Spec.Timeouts.Apply = &options.applyTimeout
|
||||
}
|
||||
if flagutils.IsSet(flags, "assert-timeout") {
|
||||
configuration.Spec.Timeouts.Assert = options.assertTimeout
|
||||
configuration.Spec.Timeouts.Assert = &options.assertTimeout
|
||||
}
|
||||
if flagutils.IsSet(flags, "error-timeout") {
|
||||
configuration.Spec.Timeouts.Error = options.errorTimeout
|
||||
configuration.Spec.Timeouts.Error = &options.errorTimeout
|
||||
}
|
||||
if flagutils.IsSet(flags, "delete-timeout") {
|
||||
configuration.Spec.Timeouts.Delete = options.deleteTimeout
|
||||
configuration.Spec.Timeouts.Delete = &options.deleteTimeout
|
||||
}
|
||||
if flagutils.IsSet(flags, "cleanup-timeout") {
|
||||
configuration.Spec.Timeouts.Cleanup = options.cleanupTimeout
|
||||
configuration.Spec.Timeouts.Cleanup = &options.cleanupTimeout
|
||||
}
|
||||
if flagutils.IsSet(flags, "exec-timeout") {
|
||||
configuration.Spec.Timeouts.Exec = options.execTimeout
|
||||
configuration.Spec.Timeouts.Exec = &options.execTimeout
|
||||
}
|
||||
if flagutils.IsSet(flags, "skip-delete") {
|
||||
configuration.Spec.Cleanup.SkipDelete = options.skipDelete
|
||||
|
@ -134,9 +135,6 @@ func Command() *cobra.Command {
|
|||
if flagutils.IsSet(flags, "template") {
|
||||
configuration.Spec.Templating.Enabled = options.template
|
||||
}
|
||||
if flagutils.IsSet(flags, "default-compiler") {
|
||||
configuration.Spec.Templating.Compiler = ptr.To(v1alpha1.Compiler(options.defaultCompiler))
|
||||
}
|
||||
if flagutils.IsSet(flags, "fail-fast") {
|
||||
configuration.Spec.Execution.FailFast = options.failFast
|
||||
}
|
||||
|
@ -148,28 +146,19 @@ func Command() *cobra.Command {
|
|||
}
|
||||
if flagutils.IsSet(flags, "report-format") {
|
||||
if configuration.Spec.Report == nil {
|
||||
configuration.Spec.Report = &v1alpha2.ReportOptions{
|
||||
Format: v1alpha2.JSONFormat,
|
||||
Name: "chainsaw-report",
|
||||
}
|
||||
configuration.Spec.Report = &v1alpha2.ReportOptions{}
|
||||
}
|
||||
configuration.Spec.Report.Format = v1alpha2.ReportFormatType(options.reportFormat)
|
||||
}
|
||||
if flagutils.IsSet(flags, "report-path") {
|
||||
if configuration.Spec.Report == nil {
|
||||
configuration.Spec.Report = &v1alpha2.ReportOptions{
|
||||
Format: v1alpha2.JSONFormat,
|
||||
Name: "chainsaw-report",
|
||||
}
|
||||
configuration.Spec.Report = &v1alpha2.ReportOptions{}
|
||||
}
|
||||
configuration.Spec.Report.Path = options.reportPath
|
||||
}
|
||||
if flagutils.IsSet(flags, "report-name") {
|
||||
if configuration.Spec.Report == nil {
|
||||
configuration.Spec.Report = &v1alpha2.ReportOptions{
|
||||
Format: v1alpha2.JSONFormat,
|
||||
Name: "chainsaw-report",
|
||||
}
|
||||
configuration.Spec.Report = &v1alpha2.ReportOptions{}
|
||||
}
|
||||
configuration.Spec.Report.Name = options.reportName
|
||||
}
|
||||
|
@ -229,63 +218,57 @@ func Command() *cobra.Command {
|
|||
if options.pauseOnFailure {
|
||||
configuration.Spec.Execution.Parallel = ptr.To(1)
|
||||
}
|
||||
fmt.Fprintf(stdOut, "- Using test file: %s\n", configuration.Spec.Discovery.TestFile)
|
||||
fmt.Fprintf(stdOut, "- TestDirs %v\n", options.testDirs)
|
||||
fmt.Fprintf(stdOut, "- SkipDelete %v\n", configuration.Spec.Cleanup.SkipDelete)
|
||||
fmt.Fprintf(stdOut, "- FailFast %v\n", configuration.Spec.Execution.FailFast)
|
||||
fmt.Fprintf(out, "- Using test file: %s\n", configuration.Spec.Discovery.TestFile)
|
||||
fmt.Fprintf(out, "- TestDirs %v\n", options.testDirs)
|
||||
fmt.Fprintf(out, "- SkipDelete %v\n", configuration.Spec.Cleanup.SkipDelete)
|
||||
fmt.Fprintf(out, "- FailFast %v\n", configuration.Spec.Execution.FailFast)
|
||||
if configuration.Spec.Report != nil {
|
||||
fmt.Fprintf(stdOut, "- ReportFormat '%v'\n", configuration.Spec.Report.Format)
|
||||
fmt.Fprintf(stdOut, "- ReportName '%v'\n", configuration.Spec.Report.Name)
|
||||
fmt.Fprintf(out, "- ReportFormat '%v'\n", configuration.Spec.Report.Format)
|
||||
fmt.Fprintf(out, "- ReportName '%v'\n", configuration.Spec.Report.Name)
|
||||
if configuration.Spec.Report.Path != "" {
|
||||
fmt.Fprintf(stdOut, "- ReportPath '%v'\n", configuration.Spec.Report.Path)
|
||||
fmt.Fprintf(out, "- ReportPath '%v'\n", configuration.Spec.Report.Path)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(stdOut, "- Namespace '%v'\n", configuration.Spec.Namespace.Name)
|
||||
fmt.Fprintf(stdOut, "- FullName %v\n", configuration.Spec.Discovery.FullName)
|
||||
fmt.Fprintf(stdOut, "- IncludeTestRegex '%v'\n", configuration.Spec.Discovery.IncludeTestRegex)
|
||||
fmt.Fprintf(stdOut, "- ExcludeTestRegex '%v'\n", configuration.Spec.Discovery.ExcludeTestRegex)
|
||||
fmt.Fprintf(stdOut, "- ApplyTimeout %v\n", configuration.Spec.Timeouts.Apply.Duration)
|
||||
fmt.Fprintf(stdOut, "- AssertTimeout %v\n", configuration.Spec.Timeouts.Assert.Duration)
|
||||
fmt.Fprintf(stdOut, "- CleanupTimeout %v\n", configuration.Spec.Timeouts.Cleanup.Duration)
|
||||
fmt.Fprintf(stdOut, "- DeleteTimeout %v\n", configuration.Spec.Timeouts.Delete.Duration)
|
||||
fmt.Fprintf(stdOut, "- ErrorTimeout %v\n", configuration.Spec.Timeouts.Error.Duration)
|
||||
fmt.Fprintf(stdOut, "- ExecTimeout %v\n", configuration.Spec.Timeouts.Exec.Duration)
|
||||
fmt.Fprintf(stdOut, "- DeletionPropagationPolicy %v\n", configuration.Spec.Deletion.Propagation)
|
||||
fmt.Fprintf(out, "- Namespace '%v'\n", configuration.Spec.Namespace.Name)
|
||||
fmt.Fprintf(out, "- FullName %v\n", configuration.Spec.Discovery.FullName)
|
||||
fmt.Fprintf(out, "- IncludeTestRegex '%v'\n", configuration.Spec.Discovery.IncludeTestRegex)
|
||||
fmt.Fprintf(out, "- ExcludeTestRegex '%v'\n", configuration.Spec.Discovery.ExcludeTestRegex)
|
||||
fmt.Fprintf(out, "- ApplyTimeout %v\n", configuration.Spec.Timeouts.ApplyDuration())
|
||||
fmt.Fprintf(out, "- AssertTimeout %v\n", configuration.Spec.Timeouts.AssertDuration())
|
||||
fmt.Fprintf(out, "- CleanupTimeout %v\n", configuration.Spec.Timeouts.CleanupDuration())
|
||||
fmt.Fprintf(out, "- DeleteTimeout %v\n", configuration.Spec.Timeouts.DeleteDuration())
|
||||
fmt.Fprintf(out, "- ErrorTimeout %v\n", configuration.Spec.Timeouts.ErrorDuration())
|
||||
fmt.Fprintf(out, "- ExecTimeout %v\n", configuration.Spec.Timeouts.ExecDuration())
|
||||
fmt.Fprintf(out, "- DeletionPropagationPolicy %v\n", configuration.Spec.Deletion.Propagation)
|
||||
if configuration.Spec.Execution.Parallel != nil && *configuration.Spec.Execution.Parallel > 0 {
|
||||
fmt.Fprintf(stdOut, "- Parallel %d\n", *configuration.Spec.Execution.Parallel)
|
||||
fmt.Fprintf(out, "- Parallel %d\n", *configuration.Spec.Execution.Parallel)
|
||||
}
|
||||
if configuration.Spec.Execution.RepeatCount != nil {
|
||||
fmt.Fprintf(stdOut, "- RepeatCount %v\n", *configuration.Spec.Execution.RepeatCount)
|
||||
fmt.Fprintf(out, "- RepeatCount %v\n", *configuration.Spec.Execution.RepeatCount)
|
||||
}
|
||||
if configuration.Spec.Execution.ForceTerminationGracePeriod != nil {
|
||||
fmt.Fprintf(stdOut, "- ForceTerminationGracePeriod %v\n", configuration.Spec.Execution.ForceTerminationGracePeriod.Duration)
|
||||
fmt.Fprintf(out, "- ForceTerminationGracePeriod %v\n", configuration.Spec.Execution.ForceTerminationGracePeriod.Duration)
|
||||
}
|
||||
if configuration.Spec.Cleanup.DelayBeforeCleanup != nil {
|
||||
fmt.Fprintf(stdOut, "- DelayBeforeCleanup %v\n", configuration.Spec.Cleanup.DelayBeforeCleanup.Duration)
|
||||
fmt.Fprintf(out, "- DelayBeforeCleanup %v\n", configuration.Spec.Cleanup.DelayBeforeCleanup.Duration)
|
||||
}
|
||||
if len(options.selector) != 0 {
|
||||
fmt.Fprintf(stdOut, "- Selector %v\n", options.selector)
|
||||
fmt.Fprintf(out, "- Selector %v\n", options.selector)
|
||||
}
|
||||
if len(options.values) != 0 {
|
||||
fmt.Fprintf(stdOut, "- Values %v\n", options.values)
|
||||
}
|
||||
fmt.Fprintf(stdOut, "- Template %v\n", configuration.Spec.Templating.Enabled)
|
||||
if configuration.Spec.Templating.Compiler != nil {
|
||||
fmt.Fprintf(stdOut, "- Default compiler %v\n", *configuration.Spec.Templating.Compiler)
|
||||
fmt.Fprintf(out, "- Values %v\n", options.values)
|
||||
}
|
||||
fmt.Fprintf(out, "- Template %v\n", configuration.Spec.Templating.Enabled)
|
||||
if len(configuration.Spec.Clusters) != 0 {
|
||||
fmt.Fprintf(stdOut, "- Clusters %v\n", configuration.Spec.Clusters)
|
||||
fmt.Fprintf(out, "- Clusters %v\n", configuration.Spec.Clusters)
|
||||
}
|
||||
if options.remarshal {
|
||||
fmt.Fprintf(stdOut, "- Remarshal %v\n", options.remarshal)
|
||||
fmt.Fprintf(out, "- Remarshal %v\n", options.remarshal)
|
||||
}
|
||||
fmt.Fprintf(stdOut, "- NoCluster %v\n", options.noCluster)
|
||||
fmt.Fprintf(stdOut, "- PauseOnFailure %v\n", options.pauseOnFailure)
|
||||
if options.shardCount > 0 {
|
||||
fmt.Fprintf(stdOut, "- Shard %v / %v\n", options.shardIndex, options.shardCount)
|
||||
}
|
||||
// load tests
|
||||
fmt.Fprintln(stdOut, "Loading tests...")
|
||||
fmt.Fprintf(out, "- NoCluster %v\n", options.noCluster)
|
||||
fmt.Fprintf(out, "- PauseOnFailure %v\n", options.pauseOnFailure)
|
||||
// loading tests
|
||||
fmt.Fprintln(out, "Loading tests...")
|
||||
if err := fsutils.CheckFolders(options.testDirs...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -301,33 +284,23 @@ func Command() *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: we may want to find a sort key here ?
|
||||
if options.shardCount > 0 && options.shardIndex < options.shardCount {
|
||||
shardLen := float64(len(tests)) / float64(options.shardCount)
|
||||
shardStart := int(shardLen * float64(options.shardIndex))
|
||||
shardEnd := int(shardLen * float64(options.shardIndex+1))
|
||||
if options.shardIndex == options.shardCount-1 {
|
||||
shardEnd = len(tests)
|
||||
}
|
||||
tests = tests[shardStart:shardEnd]
|
||||
}
|
||||
var testToRun []discovery.Test
|
||||
for _, test := range tests {
|
||||
if test.Err != nil {
|
||||
fmt.Fprintf(stdOut, "- %s (%s) - (%s)\n", test.Test.Name, test.BasePath, test.Err)
|
||||
fmt.Fprintf(out, "- %s (%s) - (%s)\n", test.Test.Name, test.BasePath, test.Err)
|
||||
} else {
|
||||
fmt.Fprintf(stdOut, "- %s (%s)\n", test.Test.Name, test.BasePath)
|
||||
fmt.Fprintf(out, "- %s (%s)\n", test.Test.Name, test.BasePath)
|
||||
testToRun = append(testToRun, test)
|
||||
}
|
||||
}
|
||||
// load values
|
||||
fmt.Fprintln(stdOut, "Loading values...")
|
||||
// loading tests
|
||||
fmt.Fprintln(out, "Loading values...")
|
||||
values, err := values.Load(options.values...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// run tests
|
||||
fmt.Fprintln(stdOut, "Running tests...")
|
||||
fmt.Fprintln(out, "Running tests...")
|
||||
var restConfig *rest.Config
|
||||
if !options.noCluster {
|
||||
cfg, err := restutils.DefaultConfig(options.kubeConfigOverrides)
|
||||
|
@ -336,63 +309,36 @@ func Command() *cobra.Command {
|
|||
}
|
||||
restConfig = cfg
|
||||
}
|
||||
var onFailure func()
|
||||
if options.pauseOnFailure {
|
||||
onFailure = func() {
|
||||
fmt.Fprintln(stdErr, "Failure detected, press ENTER to continue...")
|
||||
fmt.Fscanln(stdIn) //nolint:errcheck
|
||||
}
|
||||
}
|
||||
ctx := context.Background()
|
||||
tc, err := enginecontext.InitContext(configuration.Spec, restConfig, values)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runner := runner.New(clock, onFailure)
|
||||
// setup flags
|
||||
if err := runnerflags.SetupFlags(configuration.Spec); err != nil {
|
||||
return err
|
||||
}
|
||||
err = runner.Run(ctx, configuration.Spec.Namespace, tc, testToRun...)
|
||||
fmt.Fprintln(stdOut, "Tests Summary...")
|
||||
fmt.Fprintln(stdOut, "- Passed tests", tc.Passed())
|
||||
fmt.Fprintln(stdOut, "- Failed tests", tc.Failed())
|
||||
fmt.Fprintln(stdOut, "- Skipped tests", tc.Skipped())
|
||||
// process report
|
||||
if err == nil {
|
||||
if configuration.Spec.Report != nil && configuration.Spec.Report.Format != "" {
|
||||
fmt.Fprintln(stdOut, "Saving report...")
|
||||
if err := report.Save(tc.Report, configuration.Spec.Report.Format, configuration.Spec.Report.Path, configuration.Spec.Report.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ctx := failer.IntoContext(context.Background(), failer.New(options.pauseOnFailure))
|
||||
summary, err := runner.Run(ctx, restConfig, clock, configuration.Spec, values, testToRun...)
|
||||
if summary != nil {
|
||||
fmt.Fprintln(out, "Tests Summary...")
|
||||
fmt.Fprintln(out, "- Passed tests", summary.Passed())
|
||||
fmt.Fprintln(out, "- Failed tests", summary.Failed())
|
||||
fmt.Fprintln(out, "- Skipped tests", summary.Skipped())
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintln(stdOut, "Done with error.")
|
||||
} else if tc.Failed() > 0 {
|
||||
fmt.Fprintln(stdOut, "Done with failures.")
|
||||
fmt.Fprintln(out, "Done with error.")
|
||||
} else if summary != nil && summary.Failed() > 0 {
|
||||
fmt.Fprintln(out, "Done with failures.")
|
||||
err = errors.New("some tests failed")
|
||||
} else {
|
||||
fmt.Fprintln(stdOut, "Done.")
|
||||
fmt.Fprintln(out, "Done.")
|
||||
}
|
||||
return err
|
||||
},
|
||||
}
|
||||
config, err := config.DefaultConfiguration()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// config
|
||||
cmd.Flags().StringVar(&options.config, "config", "", "Chainsaw configuration file")
|
||||
cmd.Flags().StringSliceVar(&options.testDirs, "test-dir", nil, "Directories containing test cases to run")
|
||||
clientcmd.BindOverrideFlags(&options.kubeConfigOverrides, cmd.Flags(), clientcmd.RecommendedConfigOverrideFlags("kube-"))
|
||||
// timeouts options
|
||||
cmd.Flags().DurationVar(&options.applyTimeout.Duration, "apply-timeout", config.Spec.Timeouts.Apply.Duration, "The apply timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.assertTimeout.Duration, "assert-timeout", config.Spec.Timeouts.Assert.Duration, "The assert timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.cleanupTimeout.Duration, "cleanup-timeout", config.Spec.Timeouts.Cleanup.Duration, "The cleanup timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.deleteTimeout.Duration, "delete-timeout", config.Spec.Timeouts.Delete.Duration, "The delete timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.errorTimeout.Duration, "error-timeout", config.Spec.Timeouts.Error.Duration, "The error timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.execTimeout.Duration, "exec-timeout", config.Spec.Timeouts.Exec.Duration, "The exec timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.applyTimeout.Duration, "apply-timeout", v1alpha1.DefaultApplyTimeout, "The apply timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.assertTimeout.Duration, "assert-timeout", v1alpha1.DefaultAssertTimeout, "The assert timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.errorTimeout.Duration, "error-timeout", v1alpha1.DefaultErrorTimeout, "The error timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.deleteTimeout.Duration, "delete-timeout", v1alpha1.DefaultDeleteTimeout, "The delete timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.cleanupTimeout.Duration, "cleanup-timeout", v1alpha1.DefaultCleanupTimeout, "The cleanup timeout to use as default for configuration")
|
||||
cmd.Flags().DurationVar(&options.execTimeout.Duration, "exec-timeout", v1alpha1.DefaultExecTimeout, "The exec timeout to use as default for configuration")
|
||||
// discovery options
|
||||
cmd.Flags().StringVar(&options.testFile, "test-file", "chainsaw-test", "Name of the test file")
|
||||
cmd.Flags().BoolVar(&options.fullName, "full-name", false, "Use full test case folder path instead of folder name")
|
||||
|
@ -406,8 +352,7 @@ func Command() *cobra.Command {
|
|||
// namespace options
|
||||
cmd.Flags().StringVar(&options.namespace, "namespace", "", "Namespace to use for tests")
|
||||
// templating options
|
||||
cmd.Flags().BoolVar(&options.template, "template", config.Spec.Templating.Enabled, "If set, resources will be considered for templating")
|
||||
cmd.Flags().StringVar(&options.defaultCompiler, "default-compiler", "", "If set, configures the default compiler (jp or cel)")
|
||||
cmd.Flags().BoolVar(&options.template, "template", template.DefaultTemplate, "If set, resources will be considered for templating")
|
||||
// cleanup options
|
||||
cmd.Flags().BoolVar(&options.skipDelete, "skip-delete", false, "If set, do not delete the resources after running the tests")
|
||||
cmd.Flags().DurationVar(&options.delayBeforeCleanup.Duration, "cleanup-delay", 0, "Adds a delay between the time a test ends and the time cleanup starts")
|
||||
|
@ -415,7 +360,7 @@ func Command() *cobra.Command {
|
|||
cmd.Flags().StringVar(&options.deletionPropagationPolicy, "deletion-propagation-policy", "Background", "The deletion propagation policy (Foreground|Background|Orphan)")
|
||||
// error options
|
||||
// reporting options
|
||||
cmd.Flags().StringVar(&options.reportFormat, "report-format", "", "Test report format (JSON, XML, JUNIT-TEST, JUNIT-STEP, JUNIT-OPERATION)")
|
||||
cmd.Flags().StringVar(&options.reportFormat, "report-format", "", "Test report format (JSON|XML|nil)")
|
||||
cmd.Flags().StringVar(&options.reportName, "report-name", "chainsaw-report", "The name of the report to create")
|
||||
cmd.Flags().StringVar(&options.reportPath, "report-path", "", "The path of the report to create")
|
||||
// multi-cluster options
|
||||
|
@ -428,9 +373,6 @@ func Command() *cobra.Command {
|
|||
cmd.Flags().StringSliceVar(&options.selector, "selector", nil, "Selector (label query) to filter on")
|
||||
// external values
|
||||
cmd.Flags().StringSliceVar(&options.values, "values", nil, "Values passed to the tests")
|
||||
// sharding
|
||||
cmd.Flags().IntVar(&options.shardIndex, "shard-index", 0, "Current shard index (if `--shard-count` > 0)")
|
||||
cmd.Flags().IntVar(&options.shardCount, "shard-count", 0, "Number of shards")
|
||||
// others
|
||||
cmd.Flags().BoolVar(&options.noColor, "no-color", false, "Removes output colors")
|
||||
cmd.Flags().BoolVar(&options.remarshal, "remarshal", false, "Remarshals tests yaml to apply anchors before parsing")
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
)
|
||||
|
||||
func TestChainsawCommand(t *testing.T) {
|
||||
path := "../../../.temp"
|
||||
basePath := "../../../testdata/commands/test"
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -117,8 +116,6 @@ func TestChainsawCommand(t *testing.T) {
|
|||
args: []string{
|
||||
"--config",
|
||||
filepath.Join(basePath, "config/config_all_fields.yaml"),
|
||||
"--report-path",
|
||||
path,
|
||||
},
|
||||
wantErr: false,
|
||||
out: filepath.Join(basePath, "config_all_fields.txt"),
|
||||
|
@ -138,8 +135,6 @@ func TestChainsawCommand(t *testing.T) {
|
|||
"--parallel=24",
|
||||
"--repeat-count=12",
|
||||
"--report-format=XML",
|
||||
"--report-path",
|
||||
path,
|
||||
"--report-name=foo",
|
||||
"--namespace=bar",
|
||||
"--full-name=true",
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue