From 9740ba806a5f3c56bea66de6f59c2d2e9679fb3f Mon Sep 17 00:00:00 2001 From: zamaz <71521611+zachariahmiller@users.noreply.github.com> Date: Wed, 27 Mar 2024 15:29:28 -0400 Subject: [PATCH] feat(tools): add yq (#2406) ## Description Adds `zarf tools yq` ## Related Issue Fixes #2384 ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Other (security config, docs update, etc) ## Checklist before merging - [x] Test, docs, adr added or updated as needed - [x] [Contributor Guide Steps](https://github.com/defenseunicorns/zarf/blob/main/CONTRIBUTING.md#developer-workflow) followed --- .../100-cli-commands/zarf_tools.md | 1 + .../100-cli-commands/zarf_tools_yq.md | 81 ++++++++++++++++ .../zarf_tools_yq_eval-all.md | 91 ++++++++++++++++++ .../100-cli-commands/zarf_tools_yq_eval.md | 93 +++++++++++++++++++ go.mod | 13 ++- go.sum | 33 ++++++- src/cmd/common/vendor.go | 1 + src/cmd/internal.go | 8 ++ src/cmd/tools/yq.go | 28 ++++++ src/config/lang/english.go | 43 +++++++++ src/test/e2e/00_use_cli_test.go | 20 ++++ src/test/packages/00-yq-checks/file1.yaml | 3 + src/test/packages/00-yq-checks/file2.yaml | 3 + 13 files changed, 410 insertions(+), 8 deletions(-) create mode 100644 docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq.md create mode 100644 docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq_eval-all.md create mode 100644 docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq_eval.md create mode 100644 src/cmd/tools/yq.go create mode 100644 src/test/packages/00-yq-checks/file1.yaml create mode 100644 src/test/packages/00-yq-checks/file2.yaml diff --git a/docs/2-the-zarf-cli/100-cli-commands/zarf_tools.md b/docs/2-the-zarf-cli/100-cli-commands/zarf_tools.md index fb8193952c..587283fccf 100644 --- a/docs/2-the-zarf-cli/100-cli-commands/zarf_tools.md +++ b/docs/2-the-zarf-cli/100-cli-commands/zarf_tools.md @@ -38,3 +38,4 @@ Collection of additional tools to make airgap easier * [zarf tools sbom](zarf_tools_sbom.md) - Generates a Software Bill of Materials (SBOM) for the given package * [zarf tools update-creds](zarf_tools_update-creds.md) - Updates the credentials for deployed Zarf services. Pass a service key to update credentials for a single service * [zarf tools wait-for](zarf_tools_wait-for.md) - Waits for a given Kubernetes resource to be ready +* [zarf tools yq](zarf_tools_yq.md) - yq is a lightweight and portable command-line data file processor. diff --git a/docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq.md b/docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq.md new file mode 100644 index 0000000000..6850cd2924 --- /dev/null +++ b/docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq.md @@ -0,0 +1,81 @@ +# zarf tools yq + + +yq is a lightweight and portable command-line data file processor. + +## Synopsis + +yq is a portable command-line data file processor (https://github.com/mikefarah/yq/) +See https://mikefarah.gitbook.io/yq/ for detailed documentation and examples. + +``` +zarf tools yq [flags] +``` + +## Examples + +``` + +# yq defaults to 'eval' command if no command is specified. See "zarf tools yq eval --help" for more examples. + +# read the "stuff" node from "myfile.yml" +zarf tools yq '.stuff' < myfile.yml + +# update myfile.yml in place +zarf tools yq -i '.stuff = "foo"' myfile.yml + +# print contents of sample.json as idiomatic YAML +zarf tools yq -P sample.json + +``` + +## Options + +``` + -C, --colors force print with colors + --csv-auto-parse parse CSV YAML/JSON values (default true) + --csv-separator char CSV Separator character (default ,) + -e, --exit-status set exit status if there are no matches or null or false is returned + --expression string forcibly set the expression argument. Useful when yq argument detection thinks your expression is a file. + --from-file string Load expression from specified file. + -f, --front-matter string (extract|process) first input as yaml front-matter. Extract will pull out the yaml content, process will run the expression against the yaml content, leaving the remaining data intact + --header-preprocess Slurp any header comments and separators before processing expression. (default true) + -h, --help help for yq + -I, --indent int sets indent level for output (default 2) + -i, --inplace update the file in place of first file given. + -p, --input-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|lua|l] parse format for input. (default "auto") + --lua-globals output keys as top-level global variables + --lua-prefix string prefix (default "return ") + --lua-suffix string suffix (default ";\n") + --lua-unquoted output unquoted string keys (e.g. {foo="bar"}) + -M, --no-colors force print with no colors + -N, --no-doc Don't print document separators (---) + -0, --nul-output Use NUL char to separate values. If unwrap scalar is also set, fail if unwrapped scalar contains NUL char. + -n, --null-input Don't read input, simply evaluate the expression given. Useful for creating docs from scratch. + -o, --output-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|shell|s|lua|l] output format type. (default "auto") + -P, --prettyPrint pretty print, shorthand for '... style = ""' + --properties-array-brackets use [x] in array paths (e.g. for SpringBoot) + --properties-separator string separator to use between keys and values (default " = ") + -s, --split-exp string print each result (or doc) into a file named (exp). [exp] argument must return a string. You can use $index in the expression as the result counter. + --split-exp-file string Use a file to specify the split-exp expression. + --string-interpolation Toggles strings interpolation of \(exp) (default true) + --tsv-auto-parse parse TSV YAML/JSON values (default true) + -r, --unwrapScalar unwrap scalar, print the value with no quotes, colors or comments. Defaults to true for yaml (default true) + -v, --verbose verbose mode + -V, --version Print version information and quit + --xml-attribute-prefix string prefix for xml attributes (default "+@") + --xml-content-name string name for xml content (if no attribute name is present). (default "+content") + --xml-directive-name string name for xml directives (e.g. ) (default "+directive") + --xml-keep-namespace enables keeping namespace after parsing attributes (default true) + --xml-proc-inst-prefix string prefix for xml processing instructions (e.g. ) (default "+p_") + --xml-raw-token enables using RawToken method instead Token. Commonly disables namespace translations. See https://pkg.go.dev/encoding/xml#Decoder.RawToken for details. (default true) + --xml-skip-directives skip over directives (e.g. ) + --xml-skip-proc-inst skip over process instructions (e.g. ) + --xml-strict-mode enables strict parsing of XML. See https://pkg.go.dev/encoding/xml for more details. +``` + +## SEE ALSO + +* [zarf tools](zarf_tools.md) - Collection of additional tools to make airgap easier +* [zarf tools yq eval](zarf_tools_yq_eval.md) - (default) Apply the expression to each document in each yaml file in sequence +* [zarf tools yq eval-all](zarf_tools_yq_eval-all.md) - Loads _all_ yaml documents of _all_ yaml files and runs expression once diff --git a/docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq_eval-all.md b/docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq_eval-all.md new file mode 100644 index 0000000000..6ab4d54349 --- /dev/null +++ b/docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq_eval-all.md @@ -0,0 +1,91 @@ +# zarf tools yq eval-all + + +Loads _all_ yaml documents of _all_ yaml files and runs expression once + +## Synopsis + +yq is a portable command-line data file processor (https://github.com/mikefarah/yq/) +See https://mikefarah.gitbook.io/yq/ for detailed documentation and examples. + +# Evaluate All ## +This command loads _all_ yaml documents of _all_ yaml files and runs expression once +Useful when you need to run an expression across several yaml documents or files (like merge). +Note that it consumes more memory than eval. + + +``` +zarf tools yq eval-all [expression] [yaml_file1]... [flags] +``` + +## Examples + +``` + +# Merge f2.yml into f1.yml (inplace) +zarf tools yq eval-all --inplace 'select(fileIndex == 0) * select(fileIndex == 1)' f1.yml f2.yml +# the same command and expression using shortened names: +zarf tools yq ea -i 'select(fi == 0) * select(fi == 1)' f1.yml f2.yml + + +# Merge all given files +zarf tools yq ea '. as $item ireduce ({}; . * $item )' file1.yml file2.yml ... + +# Pipe from STDIN +# use '-' as a filename to pipe from STDIN +cat file2.yml | zarf tools yq ea '.a.b' file1.yml - file3.yml + +``` + +## Options + +``` + -h, --help help for eval-all +``` + +## Options inherited from parent commands + +``` + -C, --colors force print with colors + --csv-auto-parse parse CSV YAML/JSON values (default true) + --csv-separator char CSV Separator character (default ,) + -e, --exit-status set exit status if there are no matches or null or false is returned + --expression string forcibly set the expression argument. Useful when yq argument detection thinks your expression is a file. + --from-file string Load expression from specified file. + -f, --front-matter string (extract|process) first input as yaml front-matter. Extract will pull out the yaml content, process will run the expression against the yaml content, leaving the remaining data intact + --header-preprocess Slurp any header comments and separators before processing expression. (default true) + -I, --indent int sets indent level for output (default 2) + -i, --inplace update the file in place of first file given. + -p, --input-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|lua|l] parse format for input. (default "auto") + --lua-globals output keys as top-level global variables + --lua-prefix string prefix (default "return ") + --lua-suffix string suffix (default ";\n") + --lua-unquoted output unquoted string keys (e.g. {foo="bar"}) + -M, --no-colors force print with no colors + -N, --no-doc Don't print document separators (---) + -0, --nul-output Use NUL char to separate values. If unwrap scalar is also set, fail if unwrapped scalar contains NUL char. + -n, --null-input Don't read input, simply evaluate the expression given. Useful for creating docs from scratch. + -o, --output-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|shell|s|lua|l] output format type. (default "auto") + -P, --prettyPrint pretty print, shorthand for '... style = ""' + --properties-array-brackets use [x] in array paths (e.g. for SpringBoot) + --properties-separator string separator to use between keys and values (default " = ") + -s, --split-exp string print each result (or doc) into a file named (exp). [exp] argument must return a string. You can use $index in the expression as the result counter. + --split-exp-file string Use a file to specify the split-exp expression. + --string-interpolation Toggles strings interpolation of \(exp) (default true) + --tsv-auto-parse parse TSV YAML/JSON values (default true) + -r, --unwrapScalar unwrap scalar, print the value with no quotes, colors or comments. Defaults to true for yaml (default true) + -v, --verbose verbose mode + --xml-attribute-prefix string prefix for xml attributes (default "+@") + --xml-content-name string name for xml content (if no attribute name is present). (default "+content") + --xml-directive-name string name for xml directives (e.g. ) (default "+directive") + --xml-keep-namespace enables keeping namespace after parsing attributes (default true) + --xml-proc-inst-prefix string prefix for xml processing instructions (e.g. ) (default "+p_") + --xml-raw-token enables using RawToken method instead Token. Commonly disables namespace translations. See https://pkg.go.dev/encoding/xml#Decoder.RawToken for details. (default true) + --xml-skip-directives skip over directives (e.g. ) + --xml-skip-proc-inst skip over process instructions (e.g. ) + --xml-strict-mode enables strict parsing of XML. See https://pkg.go.dev/encoding/xml for more details. +``` + +## SEE ALSO + +* [zarf tools yq](zarf_tools_yq.md) - yq is a lightweight and portable command-line data file processor. diff --git a/docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq_eval.md b/docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq_eval.md new file mode 100644 index 0000000000..234ca9957e --- /dev/null +++ b/docs/2-the-zarf-cli/100-cli-commands/zarf_tools_yq_eval.md @@ -0,0 +1,93 @@ +# zarf tools yq eval + + +(default) Apply the expression to each document in each yaml file in sequence + +## Synopsis + +yq is a portable command-line data file processor (https://github.com/mikefarah/yq/) +See https://mikefarah.gitbook.io/yq/ for detailed documentation and examples. + +# Evaluate Sequence ## +This command iterates over each yaml document from each given file, applies the +expression and prints the result in sequence. + +``` +zarf tools yq eval [expression] [yaml_file1]... [flags] +``` + +## Examples + +``` + +# Reads field under the given path for each file +zarf tools yq e '.a.b' f1.yml f2.yml + +# Prints out the file +zarf tools yq e sample.yaml + +# Pipe from STDIN +# use '-' as a filename to pipe from STDIN +cat file2.yml | zarf tools yq e '.a.b' file1.yml - file3.yml + +# Creates a new yaml document +# Note that editing an empty file does not work. +zarf tools yq e -n '.a.b.c = "cat"' + +# Update a file inplace +zarf tools yq e '.a.b = "cool"' -i file.yaml + +``` + +## Options + +``` + -h, --help help for eval +``` + +## Options inherited from parent commands + +``` + -C, --colors force print with colors + --csv-auto-parse parse CSV YAML/JSON values (default true) + --csv-separator char CSV Separator character (default ,) + -e, --exit-status set exit status if there are no matches or null or false is returned + --expression string forcibly set the expression argument. Useful when yq argument detection thinks your expression is a file. + --from-file string Load expression from specified file. + -f, --front-matter string (extract|process) first input as yaml front-matter. Extract will pull out the yaml content, process will run the expression against the yaml content, leaving the remaining data intact + --header-preprocess Slurp any header comments and separators before processing expression. (default true) + -I, --indent int sets indent level for output (default 2) + -i, --inplace update the file in place of first file given. + -p, --input-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|lua|l] parse format for input. (default "auto") + --lua-globals output keys as top-level global variables + --lua-prefix string prefix (default "return ") + --lua-suffix string suffix (default ";\n") + --lua-unquoted output unquoted string keys (e.g. {foo="bar"}) + -M, --no-colors force print with no colors + -N, --no-doc Don't print document separators (---) + -0, --nul-output Use NUL char to separate values. If unwrap scalar is also set, fail if unwrapped scalar contains NUL char. + -n, --null-input Don't read input, simply evaluate the expression given. Useful for creating docs from scratch. + -o, --output-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|shell|s|lua|l] output format type. (default "auto") + -P, --prettyPrint pretty print, shorthand for '... style = ""' + --properties-array-brackets use [x] in array paths (e.g. for SpringBoot) + --properties-separator string separator to use between keys and values (default " = ") + -s, --split-exp string print each result (or doc) into a file named (exp). [exp] argument must return a string. You can use $index in the expression as the result counter. + --split-exp-file string Use a file to specify the split-exp expression. + --string-interpolation Toggles strings interpolation of \(exp) (default true) + --tsv-auto-parse parse TSV YAML/JSON values (default true) + -r, --unwrapScalar unwrap scalar, print the value with no quotes, colors or comments. Defaults to true for yaml (default true) + -v, --verbose verbose mode + --xml-attribute-prefix string prefix for xml attributes (default "+@") + --xml-content-name string name for xml content (if no attribute name is present). (default "+content") + --xml-directive-name string name for xml directives (e.g. ) (default "+directive") + --xml-keep-namespace enables keeping namespace after parsing attributes (default true) + --xml-proc-inst-prefix string prefix for xml processing instructions (e.g. ) (default "+p_") + --xml-raw-token enables using RawToken method instead Token. Commonly disables namespace translations. See https://pkg.go.dev/encoding/xml#Decoder.RawToken for details. (default true) + --xml-skip-directives skip over directives (e.g. ) + --xml-skip-proc-inst skip over process instructions (e.g. ) + --xml-strict-mode enables strict parsing of XML. See https://pkg.go.dev/encoding/xml for more details. +``` + +## SEE ALSO + +* [zarf tools yq](zarf_tools_yq.md) - yq is a lightweight and portable command-line data file processor. diff --git a/go.mod b/go.mod index a3cd705256..93febdd173 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.9.0 github.com/xeipuuv/gojsonschema v1.2.0 - golang.org/x/crypto v0.19.0 + golang.org/x/crypto v0.21.0 golang.org/x/sync v0.6.0 golang.org/x/term v0.18.0 helm.sh/helm/v3 v3.14.2 @@ -106,9 +106,11 @@ require ( github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect github.com/ThalesIgnite/crypto11 v1.2.5 // indirect + github.com/a8m/envsubst v1.4.2 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/acobaugh/osrelease v0.1.0 // indirect github.com/adrg/xdg v0.4.0 // indirect + github.com/alecthomas/participle/v2 v2.1.1 // indirect github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect github.com/alibabacloud-go/cr-20160607 v1.0.1 // indirect github.com/alibabacloud-go/cr-20181201 v1.0.10 // indirect @@ -208,6 +210,7 @@ require ( github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/elliotchance/orderedmap v1.5.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emicklei/proto v1.12.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -249,6 +252,7 @@ require ( github.com/go-restruct/restruct v1.2.0-alpha // indirect github.com/go-test/deep v1.1.0 // indirect github.com/gobwas/glob v0.2.3 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.0 // indirect @@ -335,6 +339,7 @@ require ( github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect + github.com/mikefarah/yq/v4 v4.43.1 github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -378,7 +383,7 @@ require ( github.com/pborman/indent v1.2.1 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.0 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect @@ -447,6 +452,7 @@ require ( github.com/xlab/treeprint v1.2.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yashtewari/glob-intersection v0.2.0 // indirect + github.com/yuin/gopher-lua v1.1.1 // indirect github.com/zclconf/go-cty v1.14.0 // indirect github.com/zeebo/errs v1.3.0 // indirect github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 // indirect @@ -465,7 +471,7 @@ require ( go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.21.0 // indirect + golang.org/x/net v0.22.0 // indirect golang.org/x/oauth2 v0.17.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect @@ -483,6 +489,7 @@ require ( gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 87b931ddbb..f4ff7a837b 100644 --- a/go.sum +++ b/go.sum @@ -304,6 +304,8 @@ github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/O github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E= github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE= +github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg= +github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE= @@ -312,8 +314,14 @@ github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/alecthomas/assert/v2 v2.3.0 h1:mAsH2wmvjsuvyBvAmCtm7zFsBlb8mIHx5ySLVdDZXL0= +github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b h1:doCpXjVwui6HUN+xgNsNS3SZ0/jUZ68Eb+mJRNOZfog= github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= +github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8= +github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -653,6 +661,8 @@ github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elliotchance/orderedmap v1.5.1 h1:G1X4PYlljzimbdQ3RXmtIZiQ9d6aRQ3sH1nzjq5mECE= +github.com/elliotchance/orderedmap v1.5.1/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/proto v1.12.1 h1:6n/Z2pZAnBwuhU66Gs8160B8rrrYKo7h2F2sCOnNceE= @@ -821,6 +831,8 @@ github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XE github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.11.3 h1:B3W9IdWbvrUu2OYQGwvU1nZtvMQJPBKgBUuweJjLj6I= github.com/goccy/go-yaml v1.11.3/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -1065,6 +1077,8 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/vault/api v1.10.0 h1:/US7sIjWN6Imp4o/Rj1Ce2Nr5bki/AXi9vAW3p2tOJQ= github.com/hashicorp/vault/api v1.10.0/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM= @@ -1254,6 +1268,8 @@ github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60 github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mikefarah/yq/v4 v4.43.1 h1:1bCrQwVDhjGnPboQidy30hu6U2TCd8sUQTy1hKCHOGI= +github.com/mikefarah/yq/v4 v4.43.1/go.mod h1:jcSqtyUKbPWvwaa8cNw8Ej4rmPb3iWE8zYvpkTvM7oc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= @@ -1382,8 +1398,8 @@ github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= +github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/petergtz/pegomock v2.9.0+incompatible h1:BKfb5XfkJfehe5T+O1xD4Zm26Sb9dnRj7tHxLYwUPiI= @@ -1397,6 +1413,8 @@ github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -1683,6 +1701,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= @@ -1769,8 +1789,9 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1878,8 +1899,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2387,6 +2408,8 @@ gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= 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/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= diff --git a/src/cmd/common/vendor.go b/src/cmd/common/vendor.go index 29694c3967..5f10726204 100644 --- a/src/cmd/common/vendor.go +++ b/src/cmd/common/vendor.go @@ -31,6 +31,7 @@ var vendorCmds = []string{ "r", "helm", "h", + "yq", } // CheckVendorOnlyFromArgs checks if the command being run is a vendor-only command diff --git a/src/cmd/internal.go b/src/cmd/internal.go index 213385e8e3..ecbf361bc3 100644 --- a/src/cmd/internal.go +++ b/src/cmd/internal.go @@ -103,6 +103,14 @@ var genCLIDocs = &cobra.Command{ } }) } + + if toolCmd.Use == "yq" { + for _, subCmd := range toolCmd.Commands() { + if subCmd.Name() == "shell-completion" { + subCmd.Hidden = true + } + } + } } } } diff --git a/src/cmd/tools/yq.go b/src/cmd/tools/yq.go new file mode 100644 index 0000000000..e1cebd2b74 --- /dev/null +++ b/src/cmd/tools/yq.go @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2021-Present The Zarf Authors + +// Package tools contains the CLI commands for Zarf. +package tools + +import ( + "github.com/defenseunicorns/zarf/src/config/lang" + yq "github.com/mikefarah/yq/v4/cmd" + +) + +func init() { + + yqCmd := yq.New() + yqCmd.Example = lang.CmdToolsYqExample + yqCmd.Use = "yq" + for _, subCmd := range yqCmd.Commands() { + if subCmd.Name() == "eval" { + subCmd.Example = lang.CmdToolsYqEvalExample + } + if subCmd.Name() == "eval-all" { + subCmd.Example = lang.CmdToolsYqEvalAllExample + } + } + + toolsCmd.AddCommand(yqCmd) +} diff --git a/src/config/lang/english.go b/src/config/lang/english.go index 99fdab80e3..9c9219a231 100644 --- a/src/config/lang/english.go +++ b/src/config/lang/english.go @@ -477,7 +477,50 @@ $ zarf tools registry digest reg.example.com/stefanprodan/podinfo:6.4.0 CmdToolsGetGitPasswdShort = "[Deprecated] Returns the push user's password for the Git server" CmdToolsGetGitPasswdLong = "[Deprecated] Reads the password for a user with push access to the configured Git server in Zarf State. Note that this command has been replaced by 'zarf tools get-creds git' and will be removed in Zarf v1.0.0." CmdToolsGetGitPasswdDeprecation = "Deprecated: This command has been replaced by 'zarf tools get-creds git' and will be removed in Zarf v1.0.0." + CmdToolsYqExample = ` +# yq defaults to 'eval' command if no command is specified. See "zarf tools yq eval --help" for more examples. +# read the "stuff" node from "myfile.yml" +zarf tools yq '.stuff' < myfile.yml + +# update myfile.yml in place +zarf tools yq -i '.stuff = "foo"' myfile.yml + +# print contents of sample.json as idiomatic YAML +zarf tools yq -P sample.json +` + CmdToolsYqEvalAllExample = ` +# Merge f2.yml into f1.yml (inplace) +zarf tools yq eval-all --inplace 'select(fileIndex == 0) * select(fileIndex == 1)' f1.yml f2.yml +## the same command and expression using shortened names: +zarf tools yq ea -i 'select(fi == 0) * select(fi == 1)' f1.yml f2.yml + + +# Merge all given files +zarf tools yq ea '. as $item ireduce ({}; . * $item )' file1.yml file2.yml ... + +# Pipe from STDIN +## use '-' as a filename to pipe from STDIN +cat file2.yml | zarf tools yq ea '.a.b' file1.yml - file3.yml +` + CmdToolsYqEvalExample = ` +# Reads field under the given path for each file +zarf tools yq e '.a.b' f1.yml f2.yml + +# Prints out the file +zarf tools yq e sample.yaml + +# Pipe from STDIN +## use '-' as a filename to pipe from STDIN +cat file2.yml | zarf tools yq e '.a.b' file1.yml - file3.yml + +# Creates a new yaml document +## Note that editing an empty file does not work. +zarf tools yq e -n '.a.b.c = "cat"' + +# Update a file inplace +zarf tools yq e '.a.b = "cool"' -i file.yaml +` CmdToolsMonitorShort = "Launches a terminal UI to monitor the connected cluster using K9s." CmdToolsHelmShort = "Subset of the Helm CLI included with Zarf to help manage helm charts." diff --git a/src/test/e2e/00_use_cli_test.go b/src/test/e2e/00_use_cli_test.go index f6acc4840e..eec380619e 100644 --- a/src/test/e2e/00_use_cli_test.go +++ b/src/test/e2e/00_use_cli_test.go @@ -213,4 +213,24 @@ func TestUseCLI(t *testing.T) { require.FileExists(t, tlsKey) }) + t.Run("zarf tools yq should function appropriately across different uses", func(t *testing.T) { + t.Parallel() + + file := "src/test/packages/00-yq-checks/file1.yaml" + otherFile := "src/test/packages/00-yq-checks/file2.yaml" + + // Test that yq can eval properly + _, stdErr, err := e2e.Zarf("tools", "yq", "eval", "-i", `.items[1].name = "renamed-item"`, file) + require.NoError(t, err, stdErr) + stdOut, stdErr, err := e2e.Zarf("tools", "yq", ".items[1].name", file) + require.Contains(t, stdOut, "renamed-item") + + // Test that yq ea can be used properly + _, stdErr, err = e2e.Zarf("tools", "yq", "eval-all", "-i", `. as $doc ireduce ({}; .items += $doc.items)`, file, otherFile) + require.NoError(t, err, stdErr) + stdOut, stdErr, err = e2e.Zarf("tools", "yq", "e", ".items | length", file) + require.Equal(t, "4\n", stdOut) + + }) } + diff --git a/src/test/packages/00-yq-checks/file1.yaml b/src/test/packages/00-yq-checks/file1.yaml new file mode 100644 index 0000000000..f4256bbf42 --- /dev/null +++ b/src/test/packages/00-yq-checks/file1.yaml @@ -0,0 +1,3 @@ +items: + - name: item1 + - name: renamed-item diff --git a/src/test/packages/00-yq-checks/file2.yaml b/src/test/packages/00-yq-checks/file2.yaml new file mode 100644 index 0000000000..7e5c503fe5 --- /dev/null +++ b/src/test/packages/00-yq-checks/file2.yaml @@ -0,0 +1,3 @@ +items: + - name: item3 + - name: item4