From d2abf4e9a640dddf517659239a34fae64223f98c Mon Sep 17 00:00:00 2001 From: Austin Abro <37223396+AustinAbro321@users.noreply.github.com> Date: Thu, 25 Apr 2024 12:58:42 -0400 Subject: [PATCH 1/3] fix: broken schema from unexpanded embedded variables (#2458) ## Description schema is broken due to unexpanded variables, expanding them now ## Checklist before merging - [ ] Test, docs, adr added or updated as needed - [ ] [Contributor Guide Steps](https://github.com/defenseunicorns/zarf/blob/main/.github/CONTRIBUTING.md#developer-workflow) followed --- Makefile | 4 +- go.mod | 6 +- go.sum | 13 +- hack/create-zarf-schema.sh | 13 +- src/cmd/internal.go | 5 +- zarf.schema.json | 362 ++++++++++++++++++------------------- 6 files changed, 208 insertions(+), 195 deletions(-) diff --git a/Makefile b/Makefile index b781f88e21..6adc76e641 100644 --- a/Makefile +++ b/Makefile @@ -107,7 +107,7 @@ docs-and-schema: ## Generate the Zarf Documentation and Schema ZARF_CONFIG=hack/empty-config.toml hack/create-zarf-schema.sh lint-packages-and-examples: build ## Recursively lint all zarf.yaml files in the repo except for those dedicated to tests - hack/lint-all-zarf-packages.sh $(ZARF_BIN) + hack/lint-all-zarf-packages.sh $(ZARF_BIN) false # INTERNAL: a shim used to build the agent image only if needed on Windows using the `test` command init-package-local-agent: @@ -226,4 +226,4 @@ cve-report: ## Create a CVE report for the current project (must `brew install g lint-go: ## Run revive to lint the go code (must `brew install revive` first) revive -config hack/revive.toml -exclude src/cmd/viper.go -formatter stylish ./src/... - hack/check-spdx-go.sh src >/dev/null || (echo "SPDX check for go failed, please run 'hack/check-spdx-go.sh src' to see the errors" && exit 1) + @hack/check-spdx-go.sh src >/dev/null || (echo "SPDX check for go failed, please run 'hack/check-spdx-go.sh src' to see the errors" && exit 1) diff --git a/go.mod b/go.mod index e09830fca2..9e67298f72 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/Masterminds/semver/v3 v3.2.1 github.com/agnivade/levenshtein v1.1.1 - github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b github.com/anchore/clio v0.0.0-20240307182142-fb5fc4c9db3c github.com/anchore/stereoscope v0.0.1 github.com/anchore/syft v0.100.0 @@ -28,6 +27,7 @@ require ( github.com/gofrs/flock v0.8.1 github.com/google/go-containerregistry v0.19.0 github.com/gosuri/uitable v0.0.4 + github.com/invopop/jsonschema v0.12.0 github.com/mholt/archiver/v3 v3.5.1 github.com/moby/moby v24.0.9+incompatible github.com/opencontainers/image-spec v1.1.0 @@ -154,6 +154,7 @@ require ( github.com/aws/smithy-go v1.19.0 // indirect github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect @@ -161,6 +162,7 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/bmatcuk/doublestar/v2 v2.0.4 // indirect github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect + github.com/buger/jsonparser v1.1.1 // indirect github.com/buildkite/agent/v3 v3.62.0 // indirect github.com/buildkite/go-pipeline v0.3.2 // indirect github.com/buildkite/interpolate v0.0.0-20200526001904-07f35b4ae251 // indirect @@ -292,7 +294,6 @@ require ( github.com/hashicorp/hcl v1.0.1-vault-5 // indirect github.com/hashicorp/vault/api v1.10.0 // indirect github.com/huandu/xstrings v1.4.0 // indirect - github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/in-toto/in-toto-golang v0.9.0 // indirect @@ -443,6 +444,7 @@ require ( github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 // indirect github.com/wagoodman/go-presenter v0.0.0-20211015174752-f9c01afc824b // indirect github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/xanzy/go-gitlab v0.96.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect diff --git a/go.sum b/go.sum index 7fe2a516c2..5a5ab0acbf 100644 --- a/go.sum +++ b/go.sum @@ -314,8 +314,6 @@ github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRB 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= @@ -462,6 +460,8 @@ github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945- github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8/go.mod h1:2JF49jcDOrLStIXN/j/K1EKRq8a8R2qRnlZA6/o/c7c= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/becheran/wildmatch-go v1.0.0 h1:mE3dGGkTmpKtT4Z+88t8RStG40yN9T+kFEGj2PZFSzA= github.com/becheran/wildmatch-go v1.0.0/go.mod h1:gbMvj0NtVdJ15Mg/mH9uxk2R1QCistMyU7d9KFzroX4= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -483,6 +483,8 @@ github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oM github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/buildkite/agent/v3 v3.62.0 h1:yvzSjI8Lgifw883I8m9u8/L/Thxt4cLFd5aWPn3gg70= github.com/buildkite/agent/v3 v3.62.0/go.mod h1:jN6SokGXrVNNIpI0BGQ+j5aWeI3gin8F+3zwA5Q6gqM= github.com/buildkite/go-pipeline v0.3.2 h1:SW4EaXNwfjow7xDRPGgX0Rcx+dPj5C1kV9LKCLjWGtM= @@ -1085,8 +1087,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= -github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -1101,6 +1101,8 @@ github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= +github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY= @@ -1599,7 +1601,6 @@ github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -1667,6 +1668,8 @@ github.com/wagoodman/go-presenter v0.0.0-20211015174752-f9c01afc824b h1:uWNQ0khA github.com/wagoodman/go-presenter v0.0.0-20211015174752-f9c01afc824b/go.mod h1:ewlIKbKV8l+jCj8rkdXIs361ocR5x3qGyoCSca47Gx8= github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 h1:0KGbf+0SMg+UFy4e1A/CPVvXn21f1qtWdeJwxZFoQG8= github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/xanzy/go-gitlab v0.96.0 h1:LGkZ+wSNMRtHIBaYE4Hq3dZVjprwHv3Y1+rhKU3WETs= github.com/xanzy/go-gitlab v0.96.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= diff --git a/hack/create-zarf-schema.sh b/hack/create-zarf-schema.sh index 46bd7451df..91fa767bf5 100755 --- a/hack/create-zarf-schema.sh +++ b/hack/create-zarf-schema.sh @@ -6,5 +6,16 @@ set -euo pipefail go run main.go internal gen-config-schema > zarf.schema.json # Adds pattern properties to all definitions to allow for yaml extensions -jq '.definitions |= map_values(. + {"patternProperties": {"^x-": {}}})' zarf.schema.json > temp_zarf.schema.json +jq ' + def addPatternProperties: + . + + if has("properties") then + {"patternProperties": {"^x-": {}}} + else + {} + end; + + walk(if type == "object" then addPatternProperties else . end) +' zarf.schema.json > temp_zarf.schema.json + mv temp_zarf.schema.json zarf.schema.json diff --git a/src/cmd/internal.go b/src/cmd/internal.go index 8ea6113113..55b7f39232 100644 --- a/src/cmd/internal.go +++ b/src/cmd/internal.go @@ -11,7 +11,6 @@ import ( "path/filepath" "strings" - "github.com/alecthomas/jsonschema" "github.com/defenseunicorns/pkg/helpers" "github.com/defenseunicorns/zarf/src/cmd/common" "github.com/defenseunicorns/zarf/src/config/lang" @@ -20,6 +19,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/cluster" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/types" + "github.com/invopop/jsonschema" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" "github.com/spf13/pflag" @@ -160,7 +160,8 @@ var genConfigSchemaCmd = &cobra.Command{ Aliases: []string{"gc"}, Short: lang.CmdInternalConfigSchemaShort, Run: func(_ *cobra.Command, _ []string) { - schema := jsonschema.Reflect(&types.ZarfPackage{}) + reflector := jsonschema.Reflector(jsonschema.Reflector{ExpandedStruct: true}) + schema := reflector.Reflect(&types.ZarfPackage{}) output, err := json.MarshalIndent(schema, "", " ") if err != nil { message.Fatal(err, lang.CmdInternalConfigSchemaErr) diff --git a/zarf.schema.json b/zarf.schema.json index 633e73110e..27a8a89a4c 100644 --- a/zarf.schema.json +++ b/zarf.schema.json @@ -1,11 +1,8 @@ { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfPackage", - "definitions": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/defenseunicorns/zarf/src/types/zarf-package", + "$defs": { "BigBang": { - "required": [ - "version" - ], "properties": { "version": { "type": "string", @@ -36,19 +33,18 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "version" + ], "patternProperties": { "^x-": {} } }, "Constant": { - "required": [ - "name", - "value" - ], "properties": { "name": { - "pattern": "^[A-Z0-9_]+$", "type": "string", + "pattern": "^[A-Z0-9_]+$", "description": "The name to be used for the constant" }, "value": { @@ -70,6 +66,10 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "name", + "value" + ], "patternProperties": { "^x-": {} } @@ -117,12 +117,31 @@ } }, "InteractiveVariable": { - "required": [ - "Variable" - ], "properties": { - "Variable": { - "$ref": "#/definitions/Variable" + "name": { + "type": "string", + "pattern": "^[A-Z0-9_]+$", + "description": "The name to be used for the variable" + }, + "sensitive": { + "type": "boolean", + "description": "Whether to mark this variable as sensitive to not print it in the log" + }, + "autoIndent": { + "type": "boolean", + "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_." + }, + "pattern": { + "type": "string", + "description": "An optional regex pattern that a variable value must match before a package deployment can continue." + }, + "type": { + "type": "string", + "enum": [ + "raw", + "file" + ], + "description": "Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB)" }, "description": { "type": "string", @@ -139,6 +158,9 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "name" + ], "patternProperties": { "^x-": {} } @@ -187,13 +209,10 @@ } }, "Variable": { - "required": [ - "name" - ], "properties": { "name": { - "pattern": "^[A-Z0-9_]+$", "type": "string", + "pattern": "^[A-Z0-9_]+$", "description": "The name to be used for the variable" }, "sensitive": { @@ -209,28 +228,24 @@ "description": "An optional regex pattern that a variable value must match before a package deployment can continue." }, "type": { + "type": "string", "enum": [ "raw", "file" ], - "type": "string", "description": "Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB)" } }, "additionalProperties": false, "type": "object", + "required": [ + "name" + ], "patternProperties": { "^x-": {} } }, "ZarfBuildData": { - "required": [ - "terminal", - "user", - "architecture", - "timestamp", - "version" - ], "properties": { "terminal": { "type": "string", @@ -260,10 +275,8 @@ "description": "Any migrations that have been run on this package" }, "registryOverrides": { - "patternProperties": { - ".*": { - "type": "string" - } + "additionalProperties": { + "type": "string" }, "type": "object", "description": "Any registry domains that were overridden on package create when pulling images" @@ -294,15 +307,18 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "terminal", + "user", + "architecture", + "timestamp", + "version" + ], "patternProperties": { "^x-": {} } }, "ZarfChart": { - "required": [ - "name", - "namespace" - ], "properties": { "name": { "type": "string", @@ -357,8 +373,7 @@ }, "variables": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfChartVariable" + "$ref": "#/$defs/ZarfChartVariable" }, "type": "array", "description": "[alpha] List of variables to set in the Helm chart" @@ -366,20 +381,19 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "name", + "namespace" + ], "patternProperties": { "^x-": {} } }, "ZarfChartVariable": { - "required": [ - "name", - "description", - "path" - ], "properties": { "name": { - "pattern": "^[A-Z0-9_]+$", "type": "string", + "pattern": "^[A-Z0-9_]+$", "description": "The name of the variable" }, "description": { @@ -393,18 +407,20 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "name", + "description", + "path" + ], "patternProperties": { "^x-": {} } }, "ZarfComponent": { - "required": [ - "name" - ], "properties": { "name": { - "pattern": "^[a-z0-9\\-]*[a-z0-9]$", "type": "string", + "pattern": "^[a-z0-9\\-]*[a-z0-9]$", "description": "The name of the component" }, "description": { @@ -420,8 +436,7 @@ "description": "Do not prompt user to install this component" }, "only": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentOnlyTarget", + "$ref": "#/$defs/ZarfComponentOnlyTarget", "description": "Filter when this component is included in package creation or deployment" }, "group": { @@ -433,38 +448,33 @@ "description": "[Deprecated] Specify a path to a public key to validate signed online resources. This will be removed in Zarf v1.0.0." }, "import": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentImport", + "$ref": "#/$defs/ZarfComponentImport", "description": "Import a component from another Zarf package" }, "manifests": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfManifest" + "$ref": "#/$defs/ZarfManifest" }, "type": "array", "description": "Kubernetes manifests to be included in a generated Helm chart on package deploy" }, "charts": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfChart" + "$ref": "#/$defs/ZarfChart" }, "type": "array", "description": "Helm charts to install during package deploy" }, "dataInjections": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfDataInjection" + "$ref": "#/$defs/ZarfDataInjection" }, "type": "array", "description": "Datasets to inject into a container in the target cluster" }, "files": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfFile" + "$ref": "#/$defs/ZarfFile" }, "type": "array", "description": "Files or folders to place on disk during package deployment" @@ -484,23 +494,23 @@ "description": "List of git repos to include in the package" }, "extensions": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentExtensions", + "$ref": "#/$defs/ZarfComponentExtensions", "description": "Extend component functionality with additional features" }, "scripts": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/DeprecatedZarfComponentScripts", + "$ref": "#/$defs/DeprecatedZarfComponentScripts", "description": "[Deprecated] (replaced by actions) Custom commands to run before or after package deployment. This will be removed in Zarf v1.0.0." }, "actions": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentActions", + "$ref": "#/$defs/ZarfComponentActions", "description": "Custom commands to run at various stages of a package lifecycle" } }, "additionalProperties": false, "type": "object", + "required": [ + "name" + ], "patternProperties": { "^x-": {} } @@ -535,18 +545,17 @@ "description": "The command to run. Must specify either cmd or wait for the action to do anything." }, "shell": { - "$ref": "#/definitions/Shell", + "$ref": "#/$defs/Shell", "description": "(cmd only) Indicates a preference for a shell for the provided cmd to be executed in on supported operating systems" }, "setVariable": { - "pattern": "^[A-Z0-9_]+$", "type": "string", + "pattern": "^[A-Z0-9_]+$", "description": "[Deprecated] (replaced by setVariables) (onDeploy/cmd only) The name of a variable to update with the output of the command. This variable will be available to all remaining actions and components in the package. This will be removed in Zarf v1.0.0" }, "setVariables": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/Variable" + "$ref": "#/$defs/Variable" }, "type": "array", "description": "(onDeploy/cmd only) An array of variables to update with the output of the command. These variables will be available to all remaining actions and components in the package." @@ -556,8 +565,7 @@ "description": "Description of the action to be displayed during package execution instead of the command" }, "wait": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentActionWait", + "$ref": "#/$defs/ZarfComponentActionWait", "description": "Wait for a condition to be met before continuing. Must specify either cmd or wait for the action. See the 'zarf tools wait-for' command for more info." } }, @@ -593,8 +601,7 @@ "description": "Additional environment variables for commands" }, "shell": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/Shell", + "$ref": "#/$defs/Shell", "description": "(cmd only) Indicates a preference for a shell for the provided cmd to be executed in on supported operating systems" } }, @@ -607,35 +614,33 @@ "ZarfComponentActionSet": { "properties": { "defaults": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentActionDefaults", + "$ref": "#/$defs/ZarfComponentActionDefaults", "description": "Default configuration for all actions in this set" }, "before": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentAction" + "$ref": "#/$defs/ZarfComponentAction" }, "type": "array", "description": "Actions to run at the start of an operation" }, "after": { "items": { - "$ref": "#/definitions/ZarfComponentAction" + "$ref": "#/$defs/ZarfComponentAction" }, "type": "array", "description": "Actions to run at the end of an operation" }, "onSuccess": { "items": { - "$ref": "#/definitions/ZarfComponentAction" + "$ref": "#/$defs/ZarfComponentAction" }, "type": "array", "description": "Actions to run if all operations succeed" }, "onFailure": { "items": { - "$ref": "#/definitions/ZarfComponentAction" + "$ref": "#/$defs/ZarfComponentAction" }, "type": "array", "description": "Actions to run if all operations fail" @@ -650,13 +655,11 @@ "ZarfComponentActionWait": { "properties": { "cluster": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentActionWaitCluster", + "$ref": "#/$defs/ZarfComponentActionWaitCluster", "description": "Wait for a condition to be met in the cluster before continuing. Only one of cluster or network can be specified." }, "network": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentActionWaitNetwork", + "$ref": "#/$defs/ZarfComponentActionWaitNetwork", "description": "Wait for a condition to be met on the network before continuing. Only one of cluster or network can be specified." } }, @@ -667,10 +670,6 @@ } }, "ZarfComponentActionWaitCluster": { - "required": [ - "kind", - "name" - ], "properties": { "kind": { "type": "string", @@ -703,23 +702,23 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "kind", + "name" + ], "patternProperties": { "^x-": {} } }, "ZarfComponentActionWaitNetwork": { - "required": [ - "protocol", - "address" - ], "properties": { "protocol": { + "type": "string", "enum": [ "tcp", "http", "https" ], - "type": "string", "description": "The protocol to wait for" }, "address": { @@ -741,6 +740,10 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "protocol", + "address" + ], "patternProperties": { "^x-": {} } @@ -748,16 +751,15 @@ "ZarfComponentActions": { "properties": { "onCreate": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentActionSet", + "$ref": "#/$defs/ZarfComponentActionSet", "description": "Actions to run during package creation" }, "onDeploy": { - "$ref": "#/definitions/ZarfComponentActionSet", + "$ref": "#/$defs/ZarfComponentActionSet", "description": "Actions to run during package deployment" }, "onRemove": { - "$ref": "#/definitions/ZarfComponentActionSet", + "$ref": "#/$defs/ZarfComponentActionSet", "description": "Actions to run during package removal" } }, @@ -770,8 +772,7 @@ "ZarfComponentExtensions": { "properties": { "bigbang": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/BigBang", + "$ref": "#/$defs/BigBang", "description": "Configurations for installing Big Bang and Flux in the cluster" } }, @@ -792,8 +793,8 @@ "description": "The relative path to a directory containing a zarf.yaml to import from" }, "url": { - "pattern": "^oci://.*$", "type": "string", + "pattern": "^oci://.*$", "description": "[beta] The URL to a Zarf package to import via OCI" } }, @@ -806,16 +807,20 @@ "ZarfComponentOnlyCluster": { "properties": { "architecture": { + "type": "string", "enum": [ "amd64", "arm64" ], - "type": "string", "description": "Only create and deploy to clusters of the given architecture" }, "distros": { "items": { - "type": "string" + "type": "string", + "examples": [ + "k3s", + "eks" + ] }, "type": "array", "description": "A list of kubernetes distros this package works with (Reserved for future use)" @@ -830,17 +835,16 @@ "ZarfComponentOnlyTarget": { "properties": { "localOS": { + "type": "string", "enum": [ "linux", "darwin", "windows" ], - "type": "string", "description": "Only deploy component to specified OS" }, "cluster": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentOnlyCluster", + "$ref": "#/$defs/ZarfComponentOnlyCluster", "description": "Only deploy component to specified clusters" }, "flavor": { @@ -855,12 +859,6 @@ } }, "ZarfContainerTarget": { - "required": [ - "namespace", - "selector", - "container", - "path" - ], "properties": { "namespace": { "type": "string", @@ -884,23 +882,24 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "namespace", + "selector", + "container", + "path" + ], "patternProperties": { "^x-": {} } }, "ZarfDataInjection": { - "required": [ - "source", - "target" - ], "properties": { "source": { "type": "string", "description": "Either a path to a local folder/file or a remote URL of a file to inject into the given target pod + container" }, "target": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfContainerTarget", + "$ref": "#/$defs/ZarfContainerTarget", "description": "The target pod + container to inject the data into" }, "compress": { @@ -910,15 +909,15 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "source", + "target" + ], "patternProperties": { "^x-": {} } }, "ZarfFile": { - "required": [ - "source", - "target" - ], "properties": { "source": { "type": "string", @@ -950,14 +949,15 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "source", + "target" + ], "patternProperties": { "^x-": {} } }, "ZarfManifest": { - "required": [ - "name" - ], "properties": { "name": { "type": "string", @@ -992,18 +992,18 @@ }, "additionalProperties": false, "type": "object", + "required": [ + "name" + ], "patternProperties": { "^x-": {} } }, "ZarfMetadata": { - "required": [ - "name" - ], "properties": { "name": { - "pattern": "^[a-z0-9\\-]*[a-z0-9]$", "type": "string", + "pattern": "^[a-z0-9\\-]*[a-z0-9]$", "description": "Name to identify this Zarf package" }, "description": { @@ -1064,65 +1064,61 @@ }, "additionalProperties": false, "type": "object", - "patternProperties": { - "^x-": {} - } - }, - "ZarfPackage": { "required": [ - "kind", - "components" + "name" ], - "properties": { - "kind": { - "enum": [ - "ZarfInitConfig", - "ZarfPackageConfig" - ], - "type": "string", - "description": "The kind of Zarf package", - "default": "ZarfPackageConfig" - }, - "metadata": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfMetadata", - "description": "Package metadata" - }, - "build": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfBuildData", - "description": "Zarf-generated package build data" - }, - "components": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponent" - }, - "type": "array", - "description": "List of components to deploy in this package" - }, - "constants": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/Constant" - }, - "type": "array", - "description": "Constant template values applied on deploy for K8s resources" - }, - "variables": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/InteractiveVariable" - }, - "type": "array", - "description": "Variable template values applied on deploy for K8s resources" - } - }, - "additionalProperties": false, - "type": "object", "patternProperties": { "^x-": {} } } + }, + "properties": { + "kind": { + "type": "string", + "enum": [ + "ZarfInitConfig", + "ZarfPackageConfig" + ], + "description": "The kind of Zarf package", + "default": "ZarfPackageConfig" + }, + "metadata": { + "$ref": "#/$defs/ZarfMetadata", + "description": "Package metadata" + }, + "build": { + "$ref": "#/$defs/ZarfBuildData", + "description": "Zarf-generated package build data" + }, + "components": { + "items": { + "$ref": "#/$defs/ZarfComponent" + }, + "type": "array", + "description": "List of components to deploy in this package" + }, + "constants": { + "items": { + "$ref": "#/$defs/Constant" + }, + "type": "array", + "description": "Constant template values applied on deploy for K8s resources" + }, + "variables": { + "items": { + "$ref": "#/$defs/InteractiveVariable" + }, + "type": "array", + "description": "Variable template values applied on deploy for K8s resources" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "kind", + "components" + ], + "patternProperties": { + "^x-": {} } } From ccc80ae3c3ff32d434bedde1009e1c265379f1c2 Mon Sep 17 00:00:00 2001 From: Austin Abro <37223396+AustinAbro321@users.noreply.github.com> Date: Thu, 25 Apr 2024 13:48:10 -0400 Subject: [PATCH 2/3] fix: error on create if an index sha is used (#2429) ## Description Errors on create if an index sha is used and gives users options of all the other platforms they can use ## Related Issue Relates to #2425, #2394 ## Checklist before merging - [X] Test, docs, adr added or updated as needed - [ ] [Contributor Guide Steps](https://github.com/defenseunicorns/zarf/blob/main/CONTRIBUTING.md#developer-workflow) followed --------- Co-authored-by: razzle --- go.mod | 4 +- go.sum | 6 ++- .../docs/commands/zarf_tools_yq_eval.md | 2 +- src/config/config.go | 9 ++-- src/config/lang/english.go | 11 ++--- src/internal/packager/images/pull.go | 26 +++++++++++- src/pkg/packager/creator/normal.go | 9 +++- src/test/e2e/00_use_cli_test.go | 28 +++++++++---- src/test/e2e/14_create_sha_index_test.go | 41 +++++++++++++++++++ src/test/e2e/36_custom_retries_test.go | 3 +- .../14-index-sha/image-index/zarf.yaml | 9 ++++ .../14-index-sha/manifest-list/zarf.yaml | 9 ++++ 12 files changed, 129 insertions(+), 28 deletions(-) create mode 100644 src/test/e2e/14_create_sha_index_test.go create mode 100644 src/test/packages/14-index-sha/image-index/zarf.yaml create mode 100644 src/test/packages/14-index-sha/manifest-list/zarf.yaml diff --git a/go.mod b/go.mod index 9e67298f72..4be2e73cf0 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/anchore/clio v0.0.0-20240307182142-fb5fc4c9db3c github.com/anchore/stereoscope v0.0.1 github.com/anchore/syft v0.100.0 - github.com/defenseunicorns/pkg/helpers v1.0.0 + github.com/defenseunicorns/pkg/helpers v1.1.1 github.com/defenseunicorns/pkg/oci v0.0.1 github.com/derailed/k9s v0.31.7 github.com/distribution/reference v0.5.0 @@ -377,7 +377,7 @@ require ( github.com/opencontainers/selinux v1.11.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openvex/go-vex v0.2.5 // indirect - github.com/otiai10/copy v1.14.0 // indirect + github.com/otiai10/copy v1.14.0 github.com/owenrumney/go-sarif v1.1.2-0.20231003122901-1000f5e05554 // indirect github.com/package-url/packageurl-go v0.1.1 // indirect github.com/pborman/indent v1.2.1 // indirect diff --git a/go.sum b/go.sum index 5a5ab0acbf..a45dbd3c96 100644 --- a/go.sum +++ b/go.sum @@ -595,8 +595,10 @@ github.com/daviddengcn/go-colortext v1.0.0 h1:ANqDyC0ys6qCSvuEK7l3g5RaehL/Xck9EX github.com/daviddengcn/go-colortext v1.0.0/go.mod h1:zDqEI5NVUop5QPpVJUxE9UO10hRnmkD5G4Pmri9+m4c= github.com/defenseunicorns/gojsonschema v0.0.0-20231116163348-e00f069122d6 h1:gwevOZ0fxT2nzM9hrtdPbsiOHjFqDRIYMzJHba3/G6Q= github.com/defenseunicorns/gojsonschema v0.0.0-20231116163348-e00f069122d6/go.mod h1:StKLYMmPj1R5yIs6CK49EkcW1TvUYuw5Vri+LRk7Dy8= -github.com/defenseunicorns/pkg/helpers v1.0.0 h1:0o3Rs+J/g0UemZHcENBS1Z2Qw2y4FIUUrGs75iEyPb4= -github.com/defenseunicorns/pkg/helpers v1.0.0/go.mod h1:F4S5VZLDrlNWQKklzv4v9tFWjjZNhxJ1gT79j4XiLwk= +github.com/defenseunicorns/pkg/helpers v1.1.0 h1:VU8Cr3IGFEDuZrfavxmo6YXsh5FZXhehy4clKXrHNGk= +github.com/defenseunicorns/pkg/helpers v1.1.0/go.mod h1:F4S5VZLDrlNWQKklzv4v9tFWjjZNhxJ1gT79j4XiLwk= +github.com/defenseunicorns/pkg/helpers v1.1.1 h1:p3pKeK5SeFaoZUJZIX9sEsJqX1CGGMS8OpQMPgJtSqM= +github.com/defenseunicorns/pkg/helpers v1.1.1/go.mod h1:F4S5VZLDrlNWQKklzv4v9tFWjjZNhxJ1gT79j4XiLwk= github.com/defenseunicorns/pkg/oci v0.0.1 h1:EFRp3NeiwzhOWKpQ6mAxi0l9chnrAvDcIgjMr0o0fkM= github.com/defenseunicorns/pkg/oci v0.0.1/go.mod h1:zVBgRjckEAhfdvbnQrnfOP/3M/GYJkIgWtJtY7pjYdo= github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da h1:ZOjWpVsFZ06eIhnh4mkaceTiVoktdU67+M7KDHJ268M= diff --git a/site/src/content/docs/commands/zarf_tools_yq_eval.md b/site/src/content/docs/commands/zarf_tools_yq_eval.md index 58921184ab..215184cf00 100644 --- a/site/src/content/docs/commands/zarf_tools_yq_eval.md +++ b/site/src/content/docs/commands/zarf_tools_yq_eval.md @@ -41,7 +41,7 @@ cat file2.yml | zarf tools yq e '.a.b' file1.yml - file3.yml ## Note that editing an empty file does not work. zarf tools yq e -n '.a.b.c = "cat"' -# Update a file inplace +# Update a file in place zarf tools yq e '.a.b = "cool"' -i file.yaml ``` diff --git a/src/config/config.go b/src/config/config.go index b8e3e2d386..63396255b0 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -134,12 +134,11 @@ func GetCraneOptions(insecure bool, archs ...string) []crane.Option { options = append(options, crane.Insecure, crane.WithTransport(roundTripper)) } - // Add the image platform info + if archs != nil { + options = append(options, crane.WithPlatform(&v1.Platform{OS: "linux", Architecture: GetArch(archs...)})) + } + options = append(options, - crane.WithPlatform(&v1.Platform{ - OS: "linux", - Architecture: GetArch(archs...), - }), crane.WithUserAgent("zarf"), crane.WithNoClobber(true), // TODO: (@WSTARR) this is set to limit pushes to registry pods and reduce the likelihood that crane will get stuck. diff --git a/src/config/lang/english.go b/src/config/lang/english.go index b5350deb7f..1d1847d207 100644 --- a/src/config/lang/english.go +++ b/src/config/lang/english.go @@ -519,7 +519,7 @@ cat file2.yml | zarf tools yq e '.a.b' file1.yml - file3.yml ## Note that editing an empty file does not work. zarf tools yq e -n '.a.b.c = "cat"' -# Update a file inplace +# Update a file in place zarf tools yq e '.a.b = "cool"' -i file.yaml ` CmdToolsMonitorShort = "Launches a terminal UI to monitor the connected cluster using K9s." @@ -728,10 +728,11 @@ const ( // Collection of reusable error messages. var ( - ErrInitNotFound = errors.New("this command requires a zarf-init package, but one was not found on the local system. Re-run the last command again without '--confirm' to download the package") - ErrUnableToCheckArch = errors.New("unable to get the configured cluster's architecture") - ErrInterrupt = errors.New("execution cancelled due to an interrupt") - ErrUnableToGetPackages = errors.New("unable to load the Zarf Package data from the cluster") + ErrInitNotFound = errors.New("this command requires a zarf-init package, but one was not found on the local system. Re-run the last command again without '--confirm' to download the package") + ErrUnableToCheckArch = errors.New("unable to get the configured cluster's architecture") + ErrInterrupt = errors.New("execution cancelled due to an interrupt") + ErrUnableToGetPackages = errors.New("unable to load the Zarf Package data from the cluster") + ErrUnsupportedImageType = errors.New("zarf does not currently support image indexes or docker manifest lists") ) // Collection of reusable warn messages. diff --git a/src/internal/packager/images/pull.go b/src/internal/packager/images/pull.go index df839e4f07..2db0200d53 100644 --- a/src/internal/packager/images/pull.go +++ b/src/internal/packager/images/pull.go @@ -6,12 +6,14 @@ package images import ( "context" + "encoding/json" "fmt" "path/filepath" "strings" "github.com/defenseunicorns/pkg/helpers" "github.com/defenseunicorns/zarf/src/config" + "github.com/defenseunicorns/zarf/src/config/lang" "github.com/defenseunicorns/zarf/src/pkg/layout" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/transform" @@ -25,6 +27,7 @@ import ( "github.com/google/go-containerregistry/pkg/v1/empty" clayout "github.com/google/go-containerregistry/pkg/v1/layout" "github.com/google/go-containerregistry/pkg/v1/partial" + ctypes "github.com/google/go-containerregistry/pkg/v1/types" "github.com/moby/moby/client" ) @@ -271,7 +274,7 @@ func (i *ImageConfig) PullImage(src string, spinner *message.Spinner) (img v1.Im if err != nil { return nil, false, err } - } else if _, err := crane.Manifest(src, config.GetCraneOptions(i.Insecure, i.Architectures...)...); err != nil { + } else if desc, err := crane.Get(src, config.GetCraneOptions(i.Insecure)...); err != nil { // If crane is unable to pull the image, try to load it from the local docker daemon. message.Notef("Falling back to local 'docker' images, failed to find the manifest on a remote: %s", err.Error()) @@ -308,6 +311,27 @@ func (i *ImageConfig) PullImage(src string, spinner *message.Spinner) (img v1.Im return nil, false, fmt.Errorf("failed to load image from docker daemon: %w", err) } } else { + refInfo, err := transform.ParseImageRef(src) + if err != nil { + return nil, false, err + } + // Check if we have an image index or manifest list and if so error out + if refInfo.Digest != "" && (desc.MediaType == ctypes.OCIImageIndex || desc.MediaType == ctypes.DockerManifestList) { + var idx v1.IndexManifest + if err := json.Unmarshal(desc.Manifest, &idx); err != nil { + return nil, false, fmt.Errorf("%w: %w", lang.ErrUnsupportedImageType, err) + } + imageOptions := "please select one of the images below based on your platform to use instead" + imageBaseName := refInfo.Name + if refInfo.Tag != "" { + imageBaseName = fmt.Sprintf("%s:%s", imageBaseName, refInfo.Tag) + } + for _, manifest := range idx.Manifests { + imageOptions = fmt.Sprintf("%s\n %s@%s for platform %s", imageOptions, imageBaseName, manifest.Digest, manifest.Platform) + } + return nil, false, fmt.Errorf("%w: %s", lang.ErrUnsupportedImageType, imageOptions) + } + // Manifest was found, so use crane to pull the image. if img, err = crane.Pull(src, config.GetCraneOptions(i.Insecure, i.Architectures...)...); err != nil { return nil, false, fmt.Errorf("failed to pull image: %w", err) diff --git a/src/pkg/packager/creator/normal.go b/src/pkg/packager/creator/normal.go index 9e742d6cee..fed5003380 100644 --- a/src/pkg/packager/creator/normal.go +++ b/src/pkg/packager/creator/normal.go @@ -177,6 +177,7 @@ func (pc *PackageCreator) Assemble(dst *layout.PackagePaths, components []types. var pulled []images.ImgInfo var err error + ctx, cancel := context.WithCancel(context.TODO()) doPull := func() error { imgConfig := images.ImageConfig{ ImagesPath: dst.Images.Base, @@ -187,11 +188,15 @@ func (pc *PackageCreator) Assemble(dst *layout.PackagePaths, components []types. } pulled, err = imgConfig.PullAll() + if errors.Is(err, lang.ErrUnsupportedImageType) { + cancel() + } + return err } - if err := helpers.Retry(doPull, 3, 5*time.Second, message.Warnf); err != nil { - return fmt.Errorf("unable to pull images after 3 attempts: %w", err) + if err := helpers.RetryWithContext(ctx, doPull, 3, 5*time.Second, message.Warnf); err != nil { + return fmt.Errorf("unable to pull images: %w", err) } for _, imgInfo := range pulled { diff --git a/src/test/e2e/00_use_cli_test.go b/src/test/e2e/00_use_cli_test.go index efdd0f3f82..6b5a0e387c 100644 --- a/src/test/e2e/00_use_cli_test.go +++ b/src/test/e2e/00_use_cli_test.go @@ -13,6 +13,7 @@ import ( "testing" "github.com/defenseunicorns/pkg/helpers" + "github.com/otiai10/copy" "github.com/stretchr/testify/require" ) @@ -216,21 +217,32 @@ func TestUseCLI(t *testing.T) { 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" + tmpdir := t.TempDir() + originalPath := "src/test/packages/00-yq-checks" + + originalFile := filepath.Join(originalPath, "file1.yaml") + originalOtherFile := filepath.Join(originalPath, "file2.yaml") + + file := filepath.Join(tmpdir, "file1.yaml") + otherFile := filepath.Join(tmpdir, "file2.yaml") + + err := copy.Copy(originalFile, file) + require.NoError(t, err) + err = copy.Copy(originalOtherFile, otherFile) + require.NoError(t, err) // 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.NoError(t, err, stdErr) + stdOut, _, err := e2e.Zarf("tools", "yq", ".items[1].name", file) + require.NoError(t, err) 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.NoError(t, err, stdErr) + _, _, err = e2e.Zarf("tools", "yq", "eval-all", "-i", `. as $doc ireduce ({}; .items += $doc.items)`, file, otherFile) + require.NoError(t, err) + stdOut, _, err = e2e.Zarf("tools", "yq", "e", ".items | length", file) + require.NoError(t, err) require.Equal(t, "4\n", stdOut) }) } diff --git a/src/test/e2e/14_create_sha_index_test.go b/src/test/e2e/14_create_sha_index_test.go new file mode 100644 index 0000000000..9dee622c85 --- /dev/null +++ b/src/test/e2e/14_create_sha_index_test.go @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2021-Present The Zarf Authors + +// Package test provides e2e tests for Zarf. +package test + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCreateIndexShaErrors(t *testing.T) { + t.Log("E2E: CreateIndexShaErrors") + + testCases := []struct { + name string + packagePath string + expectedImageInStderr string + }{ + { + name: "Image Index", + packagePath: "src/test/packages/14-index-sha/image-index", + expectedImageInStderr: "ghcr.io/defenseunicorns/zarf/agent:v0.32.6@sha256:b3fabdc7d4ecd0f396016ef78da19002c39e3ace352ea0ae4baa2ce9d5958376", + }, + { + name: "Manifest List", + packagePath: "src/test/packages/14-index-sha/manifest-list", + expectedImageInStderr: "docker.io/defenseunicorns/zarf-game@sha256:f78e442f0f3eb3e9459b5ae6b1a8fda62f8dfe818112e7d130a4e8ae72b3cbff", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + _, stderr, err := e2e.Zarf("package", "create", tc.packagePath, "--confirm") + require.Error(t, err) + require.Contains(t, stderr, tc.expectedImageInStderr) + }) + } + +} diff --git a/src/test/e2e/36_custom_retries_test.go b/src/test/e2e/36_custom_retries_test.go index e66a6ff435..a0f33b94ac 100644 --- a/src/test/e2e/36_custom_retries_test.go +++ b/src/test/e2e/36_custom_retries_test.go @@ -27,7 +27,6 @@ func TestRetries(t *testing.T) { stdOut, stdErr, err = e2e.Zarf("package", "deploy", path.Join(tmpDir, pkgName), "--retries", "2", "--timeout", "3s", "--tmpdir", tmpDir, "--confirm") require.Error(t, err, stdOut, stdErr) - require.Contains(t, stdErr, "Retrying (1/2) in 5s:") - require.Contains(t, stdErr, "Retrying (2/2) in 10s:") + require.Contains(t, stdErr, "Retrying in 5s") require.Contains(t, stdErr, "unable to install chart after 2 attempts") } diff --git a/src/test/packages/14-index-sha/image-index/zarf.yaml b/src/test/packages/14-index-sha/image-index/zarf.yaml new file mode 100644 index 0000000000..a29c4380b9 --- /dev/null +++ b/src/test/packages/14-index-sha/image-index/zarf.yaml @@ -0,0 +1,9 @@ +kind: ZarfPackageConfig +metadata: + name: image-index + +components: + - name: baseline + required: true + images: + - ghcr.io/defenseunicorns/zarf/agent:v0.32.6@sha256:05a82656df5466ce17c3e364c16792ae21ce68438bfe06eeab309d0520c16b48 diff --git a/src/test/packages/14-index-sha/manifest-list/zarf.yaml b/src/test/packages/14-index-sha/manifest-list/zarf.yaml new file mode 100644 index 0000000000..9d7ad76b20 --- /dev/null +++ b/src/test/packages/14-index-sha/manifest-list/zarf.yaml @@ -0,0 +1,9 @@ +kind: ZarfPackageConfig +metadata: + name: manifest-list + +components: + - name: baseline + required: true + images: + - defenseunicorns/zarf-game@sha256:0b694ca1c33afae97b7471488e07968599f1d2470c629f76af67145ca64428af From e5ab989cec6aca896881a90705c21640b905cd46 Mon Sep 17 00:00:00 2001 From: Austin Abro <37223396+AustinAbro321@users.noreply.github.com> Date: Thu, 25 Apr 2024 18:56:23 -0400 Subject: [PATCH 3/3] fix: schema integration (#2463) ## Description site has broken schema integration ## Checklist before merging - [ ] Test, docs, adr added or updated as needed - [ ] [Contributor Guide Steps](https://github.com/defenseunicorns/zarf/blob/main/.github/CONTRIBUTING.md#developer-workflow) followed --- site/src/components/SchemaItemProperties.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/components/SchemaItemProperties.astro b/site/src/components/SchemaItemProperties.astro index 0b62b83ecd..d6bb1d8409 100644 --- a/site/src/components/SchemaItemProperties.astro +++ b/site/src/components/SchemaItemProperties.astro @@ -14,7 +14,7 @@ const includesElement = (key: string) => { const json = await import("../assets/zarf.schema.json"); // @ts-expect-error - We don't import a TS type for the schema, but we know it's structured correctly -const itemSchema = json.definitions[item]; +const itemSchema = json["$defs"][item]; if (unwrap) { unwrap.forEach((wrapped: string) => {