From 4c1854706adcac845f31c4ed9408511cbda7cfb2 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Tue, 21 May 2024 15:18:23 -0600 Subject: [PATCH 01/30] flavor and ref updates --- src/cmd/dev.go | 2 ++ src/config/lang/lang.go | 2 ++ src/pkg/bundle/deploy.go | 37 +++++++++++++++++++++++++++++++++++-- src/pkg/bundle/dev.go | 30 ++++++++++++++++++++++++++++-- src/types/bundle.go | 1 + src/types/options.go | 2 ++ 6 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/cmd/dev.go b/src/cmd/dev.go index 765cd701..9db9ba34 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -81,4 +81,6 @@ func init() { rootCmd.AddCommand(devCmd) devCmd.AddCommand(devDeployCmd) devDeployCmd.Flags().StringArrayVarP(&bundleCfg.DeployOpts.Packages, "packages", "p", []string{}, lang.CmdBundleDeployFlagPackages) + devDeployCmd.Flags().StringToStringVarP(&bundleCfg.DeployOpts.Refs, "refs", "r", map[string]string{}, lang.CmdBundleDeployFlagRefs) + devDeployCmd.Flags().StringToStringVarP(&bundleCfg.CreateOpts.Flavors, "flavors", "f", map[string]string{}, lang.CmdBundleCreateFlagFlavors) } diff --git a/src/config/lang/lang.go b/src/config/lang/lang.go index 7d132bc3..d996dd20 100644 --- a/src/config/lang/lang.go +++ b/src/config/lang/lang.go @@ -30,6 +30,7 @@ const ( CmdBundleCreateFlagOutput = "Specify the output (an oci:// URL) for the created bundle" CmdBundleCreateFlagSigningKey = "Path to private key file for signing bundles" CmdBundleCreateFlagSigningKeyPassword = "Password to the private key file used for signing bundles" + CmdBundleCreateFlagFlavors = "Specify which zarf package flavor you want to use. By default the ref set in the bundle yaml is used." // bundle deploy CmdBundleDeployShort = "Deploy a bundle from a local tarball or oci:// URL" @@ -38,6 +39,7 @@ const ( CmdBundleDeployFlagResume = "Only deploys packages from the bundle which haven't already been deployed" CmdBundleDeployFlagSet = "Specify deployment variables to set on the command line (KEY=value)" CmdBundleDeployFlagRetries = "Specify the number of retries for package deployments (applies to all pkgs in a bundle)" + CmdBundleDeployFlagRefs = "Specify which zarf package ref you want to deploy. By default the ref set in the bundle yaml is used." // bundle inspect CmdBundleInspectShort = "Display the metadata of a bundle" diff --git a/src/pkg/bundle/deploy.go b/src/pkg/bundle/deploy.go index 3f767ebb..80ac8544 100644 --- a/src/pkg/bundle/deploy.go +++ b/src/pkg/bundle/deploy.go @@ -46,6 +46,8 @@ func (b *Bundle) Deploy() error { for _, pkg := range b.bundle.Packages { if slices.Contains(userSpecifiedPackages, pkg.Name) { + pkg = b.setPackageRef(pkg) + pkg = b.setPackageFlavor(pkg) packagesToDeploy = append(packagesToDeploy, pkg) } } @@ -54,10 +56,41 @@ func (b *Bundle) Deploy() error { if len(userSpecifiedPackages) != len(packagesToDeploy) { return fmt.Errorf("invalid zarf packages specified by --packages") } - return deployPackages(packagesToDeploy, resume, b) + } else { + // packages not specified check any ref or flavor flags against all packages + for i, pkg := range b.bundle.Packages { + pkg = b.setPackageRef(pkg) + pkg = b.setPackageFlavor(pkg) + b.bundle.Packages[i] = pkg + } + packagesToDeploy = b.bundle.Packages } + return deployPackages(packagesToDeploy, resume, b) +} - return deployPackages(b.bundle.Packages, resume, b) +func (b *Bundle) setPackageRef(pkg types.Package) types.Package { + if b.cfg.DeployOpts.Refs != nil { + if len(b.cfg.DeployOpts.Refs) == 1 { + var value string + for _, val := range b.cfg.DeployOpts.Refs { + value = val + break + } + if value == "" { + var ref string + for key := range b.cfg.DeployOpts.Refs { + ref = key + break + } + pkg.Ref = ref + } + } else { + if ref, ok := b.cfg.DeployOpts.Refs[pkg.Name]; ok { + pkg.Ref = ref + } + } + } + return pkg } func deployPackages(packages []types.Package, resume bool, b *Bundle) error { diff --git a/src/pkg/bundle/dev.go b/src/pkg/bundle/dev.go index c36aa4dd..f620d6d6 100644 --- a/src/pkg/bundle/dev.go +++ b/src/pkg/bundle/dev.go @@ -11,7 +11,7 @@ import ( "regexp" "github.com/defenseunicorns/uds-cli/src/config" - + "github.com/defenseunicorns/uds-cli/src/types" zarfCLI "github.com/defenseunicorns/zarf/src/cmd" "github.com/defenseunicorns/zarf/src/pkg/message" zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils" @@ -48,7 +48,8 @@ func (b *Bundle) CreateZarfPkgs() { } // create local zarf package if it doesn't exist if !packageFound { - os.Args = []string{"zarf", "package", "create", pkgDir, "--confirm", "-o", pkgDir, "--skip-sbom"} + pkg = b.setPackageFlavor(pkg) + os.Args = []string{"zarf", "package", "create", pkgDir, "--confirm", "-o", pkgDir, "--skip-sbom", "--flavor", pkg.Flavor} zarfCLI.Execute() if err != nil { message.Fatalf(err, "Failed to create package %s: %s", pkg.Name, err.Error()) @@ -58,6 +59,31 @@ func (b *Bundle) CreateZarfPkgs() { } } +func (b *Bundle) setPackageFlavor(pkg types.Package) types.Package { + if b.cfg.CreateOpts.Flavors != nil { + if len(b.cfg.CreateOpts.Flavors) == 1 { + var value string + for _, val := range b.cfg.CreateOpts.Flavors { + value = val + break + } + if value == "" { + var flavor string + for key := range b.cfg.CreateOpts.Flavors { + flavor = key + break + } + pkg.Flavor = flavor + } + } else { + if flavor, ok := b.cfg.CreateOpts.Flavors[pkg.Name]; ok { + pkg.Flavor = flavor + } + } + } + return pkg +} + // SetDevSource sets the source for the bundle when in dev mode func (b *Bundle) SetDevSource(srcDir string) { srcDir = filepath.Dir(srcDir) diff --git a/src/types/bundle.go b/src/types/bundle.go index 3e7ef9e8..9604c47e 100644 --- a/src/types/bundle.go +++ b/src/types/bundle.go @@ -19,6 +19,7 @@ type Package struct { Repository string `json:"repository,omitempty" jsonschema:"description=The repository to import the package from"` Path string `json:"path,omitempty" jsonschema:"description=The local path to import the package from"` Ref string `json:"ref" jsonschema:"description=Ref (tag) of the Zarf package"` + Flavor string `json:"flavor,omitempty" jsonschema:"description=Flavor of the Zarf package"` OptionalComponents []string `json:"optionalComponents,omitempty" jsonschema:"description=List of optional components to include from the package (required components are always included)"` PublicKey string `json:"publicKey,omitempty" jsonschema:"description=The public key to use to verify the package"` Imports []BundleVariableImport `json:"imports,omitempty" jsonschema:"description=List of Zarf variables to import from another Zarf package"` diff --git a/src/types/options.go b/src/types/options.go index d2a5cbdc..4b1dda18 100644 --- a/src/types/options.go +++ b/src/types/options.go @@ -21,6 +21,7 @@ type BundleCreateOptions struct { SigningKeyPath string SigningKeyPassword string BundleFile string + Flavors map[string]string } // BundleDeployOptions is the options for the bundler.Deploy() function @@ -28,6 +29,7 @@ type BundleDeployOptions struct { Resume bool Source string Packages []string + Refs map[string]string PublicKeyPath string SetVariables map[string]string `json:"setVariables" jsonschema:"description=Key-Value map of variable names and their corresponding values that will be used by Zarf packages in a bundle"` // Variables and SharedVariables are read in from uds-config.yaml From 8d362840dc978feee15eabf077b834fae5a8cfef Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Sat, 25 May 2024 21:01:24 -0600 Subject: [PATCH 02/30] check refs and flavors on create, for local bundles --- src/cmd/dev.go | 7 ++- src/config/lang/lang.go | 12 +++-- src/pkg/bundle/create.go | 45 +++++++++++++++-- src/pkg/bundle/deploy.go | 33 ------------- src/pkg/bundle/dev.go | 41 ++++++---------- src/test/e2e/dev_test.go | 76 +++++++++++++++++++++++++++++ src/test/packages/podinfo/zarf.yaml | 44 +++++++++++++++++ src/types/options.go | 23 ++++++--- 8 files changed, 202 insertions(+), 79 deletions(-) diff --git a/src/cmd/dev.go b/src/cmd/dev.go index 517bb5b2..e48a171f 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -80,6 +80,9 @@ func init() { rootCmd.AddCommand(devCmd) devCmd.AddCommand(devDeployCmd) devDeployCmd.Flags().StringArrayVarP(&bundleCfg.DeployOpts.Packages, "packages", "p", []string{}, lang.CmdBundleDeployFlagPackages) - devDeployCmd.Flags().StringToStringVarP(&bundleCfg.DeployOpts.Refs, "refs", "r", map[string]string{}, lang.CmdBundleDeployFlagRefs) - devDeployCmd.Flags().StringToStringVarP(&bundleCfg.CreateOpts.Flavors, "flavors", "f", map[string]string{}, lang.CmdBundleCreateFlagFlavors) + devDeployCmd.Flags().StringToStringVarP(&bundleCfg.DevDeployOpts.Ref, "ref", "r", map[string]string{}, lang.CmdBundleDeployFlagRef) + devDeployCmd.Flags().StringToStringVarP(&bundleCfg.DevDeployOpts.Flavor, "flavor", "f", map[string]string{}, lang.CmdBundleCreateFlagFlavor) + devDeployCmd.Flags().StringVar(&bundleCfg.DevDeployOpts.FlavorAll, "flavor-all", "", lang.CmdBundleCreateFlagFlavorAll) + devDeployCmd.Flags().BoolVar(&bundleCfg.DevDeployOpts.ForceCreate, "force-create", false, lang.CmdBundleCreateForceCreate) + devDeployCmd.Flags().BoolVarP(&config.CommonOptions.Confirm, "confirm", "c", false, lang.CmdBundleDeployFlagConfirm) } diff --git a/src/config/lang/lang.go b/src/config/lang/lang.go index 9ff4b989..6377f525 100644 --- a/src/config/lang/lang.go +++ b/src/config/lang/lang.go @@ -29,7 +29,8 @@ const ( CmdBundleCreateFlagOutput = "Specify the output (an oci:// URL) for the created bundle" CmdBundleCreateFlagSigningKey = "Path to private key file for signing bundles" CmdBundleCreateFlagSigningKeyPassword = "Password to the private key file used for signing bundles" - CmdBundleCreateFlagFlavors = "Specify which zarf package flavor you want to use. By default the ref set in the bundle yaml is used." + CmdBundleCreateFlagFlavor = "Specify which zarf package flavor you want to use." + CmdBundleCreateFlagFlavorAll = "Specify which zarf package flavor you want to use for all packages in the bundle" // bundle deploy CmdBundleDeployShort = "Deploy a bundle from a local tarball or oci:// URL" @@ -38,7 +39,7 @@ const ( CmdBundleDeployFlagResume = "Only deploys packages from the bundle which haven't already been deployed" CmdBundleDeployFlagSet = "Specify deployment variables to set on the command line (KEY=value)" CmdBundleDeployFlagRetries = "Specify the number of retries for package deployments (applies to all pkgs in a bundle)" - CmdBundleDeployFlagRefs = "Specify which zarf package ref you want to deploy. By default the ref set in the bundle yaml is used." + CmdBundleDeployFlagRef = "Specify which zarf package ref you want to deploy. By default the ref set in the bundle yaml is used." // bundle inspect CmdBundleInspectShort = "Display the metadata of a bundle" @@ -83,7 +84,8 @@ const ( CmdZarfShort = "Run a zarf command" // uds dev - CmdDevShort = "Commands useful for developing bundles" - CmdDevDeployShort = "[beta] Creates and deploys a UDS bundle from a given directory in dev mode" - CmdDevDeployLong = "[beta] Creates and deploys a UDS bundle from a given directory in dev mode, setting package options like YOLO mode for faster iteration." + CmdDevShort = "Commands useful for developing bundles" + CmdDevDeployShort = "[beta] Creates and deploys a UDS bundle from a given directory in dev mode" + CmdDevDeployLong = "[beta] Creates and deploys a UDS bundle from a given directory in dev mode, setting package options like YOLO mode for faster iteration." + CmdBundleCreateForceCreate = "For local bundles with local packages, specify whether to create a zarf package even if it already exists." ) diff --git a/src/pkg/bundle/create.go b/src/pkg/bundle/create.go index 3c691235..9a4dddde 100644 --- a/src/pkg/bundle/create.go +++ b/src/pkg/bundle/create.go @@ -5,10 +5,12 @@ package bundle import ( + "context" "fmt" "path/filepath" "github.com/AlecAivazis/survey/v2" + "github.com/defenseunicorns/pkg/oci" "github.com/defenseunicorns/uds-cli/src/config" "github.com/defenseunicorns/uds-cli/src/pkg/bundler" "github.com/defenseunicorns/uds-cli/src/pkg/utils" @@ -17,6 +19,8 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/interactive" "github.com/defenseunicorns/zarf/src/pkg/message" zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils" + "github.com/defenseunicorns/zarf/src/pkg/zoci" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pterm/pterm" "helm.sh/helm/v3/pkg/chartutil" ) @@ -34,11 +38,6 @@ func (b *Bundle) Create() error { return err } - // Populate values from valuesFiles if provided - if err := b.processValuesFiles(); err != nil { - return err - } - // confirm creation if ok := b.confirmBundleCreation(); !ok { return fmt.Errorf("bundle creation cancelled") @@ -86,6 +85,16 @@ func (b *Bundle) Create() error { } } + // update package refs for dev deploy + if config.Dev { + if len(b.cfg.DevDeployOpts.Ref) != 0 { + for i, pkg := range b.bundle.Packages { + pkg = b.setPackageRef(pkg) + b.bundle.Packages[i] = pkg + } + } + } + opts := bundler.Options{ Bundle: &b.bundle, Output: b.cfg.CreateOpts.Output, @@ -93,9 +102,35 @@ func (b *Bundle) Create() error { SourceDir: b.cfg.CreateOpts.SourceDirectory, } bundlerClient := bundler.NewBundler(&opts) + return bundlerClient.Create() } +func (b *Bundle) setPackageRef(pkg types.Package) types.Package { + if ref, ok := b.cfg.DevDeployOpts.Ref[pkg.Name]; ok { + pkg.Ref = ref + // Get SHA from registry + url := fmt.Sprintf("%s:%s", pkg.Repository, pkg.Ref) + + platform := ocispec.Platform{ + Architecture: config.GetArch(), + OS: oci.MultiOS, + } + remote, err := zoci.NewRemote(url, platform) + if err != nil { + message.Fatalf(err, "Unable to access %s:%s", pkg.Repository, pkg.Ref) + } + if err := remote.Repo().Reference.ValidateReferenceAsDigest(); err != nil { + manifestDesc, err := remote.ResolveRoot(context.TODO()) + if err != nil { + message.Fatalf(err, "Unable to access %s:%s", pkg.Repository, pkg.Ref) + } + pkg.Ref = pkg.Ref + "@sha256:" + manifestDesc.Digest.Encoded() + } + } + return pkg +} + // confirmBundleCreation prompts the user to confirm bundle creation func (b *Bundle) confirmBundleCreation() (confirm bool) { diff --git a/src/pkg/bundle/deploy.go b/src/pkg/bundle/deploy.go index 631218dc..57c9b4a0 100644 --- a/src/pkg/bundle/deploy.go +++ b/src/pkg/bundle/deploy.go @@ -45,8 +45,6 @@ func (b *Bundle) Deploy() error { for _, pkg := range b.bundle.Packages { if slices.Contains(userSpecifiedPackages, pkg.Name) { - pkg = b.setPackageRef(pkg) - pkg = b.setPackageFlavor(pkg) packagesToDeploy = append(packagesToDeploy, pkg) } } @@ -56,42 +54,11 @@ func (b *Bundle) Deploy() error { return fmt.Errorf("invalid zarf packages specified by --packages") } } else { - // packages not specified check any ref or flavor flags against all packages - for i, pkg := range b.bundle.Packages { - pkg = b.setPackageRef(pkg) - pkg = b.setPackageFlavor(pkg) - b.bundle.Packages[i] = pkg - } packagesToDeploy = b.bundle.Packages } return deployPackages(packagesToDeploy, resume, b) } -func (b *Bundle) setPackageRef(pkg types.Package) types.Package { - if b.cfg.DeployOpts.Refs != nil { - if len(b.cfg.DeployOpts.Refs) == 1 { - var value string - for _, val := range b.cfg.DeployOpts.Refs { - value = val - break - } - if value == "" { - var ref string - for key := range b.cfg.DeployOpts.Refs { - ref = key - break - } - pkg.Ref = ref - } - } else { - if ref, ok := b.cfg.DeployOpts.Refs[pkg.Name]; ok { - pkg.Ref = ref - } - } - } - return pkg -} - func deployPackages(packages []types.Package, resume bool, b *Bundle) error { // map of Zarf pkgs and their vars bundleExportedVars := make(map[string]map[string]string) diff --git a/src/pkg/bundle/dev.go b/src/pkg/bundle/dev.go index 500bc16a..038a7c3f 100644 --- a/src/pkg/bundle/dev.go +++ b/src/pkg/bundle/dev.go @@ -27,7 +27,8 @@ func (b *Bundle) CreateZarfPkgs() { } zarfPackagePattern := `^zarf-.*\.tar\.zst$` - for _, pkg := range b.bundle.Packages { + for i := range b.bundle.Packages { + pkg := b.bundle.Packages[i] // if pkg is a local zarf package, attempt to create it if it doesn't exist if pkg.Path != "" { path := getPkgPath(pkg, config.GetArch(b.bundle.Metadata.Architecture), srcDir) @@ -48,9 +49,13 @@ func (b *Bundle) CreateZarfPkgs() { } } // create local zarf package if it doesn't exist - if !packageFound { - pkg = b.setPackageFlavor(pkg) - os.Args = []string{"zarf", "package", "create", pkgDir, "--confirm", "-o", pkgDir, "--skip-sbom", "--flavor", pkg.Flavor} + if !packageFound || b.cfg.DevDeployOpts.ForceCreate { + if len(b.cfg.DevDeployOpts.Flavor) != 0 || b.cfg.DevDeployOpts.FlavorAll != "" { + b.setPackageFlavor(&pkg) + os.Args = []string{"zarf", "package", "create", pkgDir, "--confirm", "-o", pkgDir, "--skip-sbom", "--flavor", pkg.Flavor} + } else { + os.Args = []string{"zarf", "package", "create", pkgDir, "--confirm", "-o", pkgDir, "--skip-sbom"} + } zarfCLI.Execute() if err != nil { message.Fatalf(err, "Failed to create package %s: %s", pkg.Name, err.Error()) @@ -60,29 +65,13 @@ func (b *Bundle) CreateZarfPkgs() { } } -func (b *Bundle) setPackageFlavor(pkg types.Package) types.Package { - if b.cfg.CreateOpts.Flavors != nil { - if len(b.cfg.CreateOpts.Flavors) == 1 { - var value string - for _, val := range b.cfg.CreateOpts.Flavors { - value = val - break - } - if value == "" { - var flavor string - for key := range b.cfg.CreateOpts.Flavors { - flavor = key - break - } - pkg.Flavor = flavor - } - } else { - if flavor, ok := b.cfg.CreateOpts.Flavors[pkg.Name]; ok { - pkg.Flavor = flavor - } - } +func (b *Bundle) setPackageFlavor(pkg *types.Package) { + // handle case when flavor applies to all packages + if b.cfg.DevDeployOpts.FlavorAll != "" { + pkg.Flavor = b.cfg.DevDeployOpts.FlavorAll + } else if flavor, ok := b.cfg.DevDeployOpts.Flavor[pkg.Name]; ok { + pkg.Flavor = flavor } - return pkg } // SetDevSource sets the source for the bundle when in dev mode diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index c01fe8dd..d040172d 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -49,4 +49,80 @@ func TestDevDeploy(t *testing.T) { remove(t, bundlePath) }) + + t.Run("Test dev deploy with ref flag", func(t *testing.T) { + + bundleDir := "src/test/bundles/03-local-and-remote" + + cmd := strings.Split(fmt.Sprintf("dev deploy %s --ref %s", bundleDir, "nginx=0.0.2"), " ") + _, _, err := e2e.UDS(cmd...) + require.NoError(t, err) + + cmd = strings.Split("zarf tools kubectl get deployment -n nginx nginx-deployment -o=jsonpath='{.spec.template.spec.containers[0].image}'", " ") + ref, _, err := e2e.UDS(cmd...) + require.Contains(t, ref, "nginx:1.26.0") + require.NoError(t, err) + + cmd = strings.Split("zarf tools kubectl delete ns podinfo nginx zarf", " ") + _, _, err = e2e.UDS(cmd...) + require.NoError(t, err) + }) + + t.Run("Test dev deploy with flavors flag", func(t *testing.T) { + + bundleDir := "src/test/bundles/03-local-and-remote" + + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavors %s", bundleDir, "podinfo=three"), " ") + _, _, err := e2e.UDS(cmd...) + require.NoError(t, err) + + cmd = strings.Split("zarf tools kubectl get deployment -n podinfo-flavor podinfo -o=jsonpath='{.spec.template.spec.containers[0].image}'", " ") + ref, _, err := e2e.UDS(cmd...) + require.Contains(t, ref, "ghcr.io/stefanprodan/podinfo:6.6.3") + require.NoError(t, err) + + cmd = strings.Split("zarf tools kubectl delete ns podinfo nginx zarf podinfo-flavor", " ") + _, _, err = e2e.UDS(cmd...) + require.NoError(t, err) + }) + t.Run("Test dev deploy with global flavor", func(t *testing.T) { + + bundleDir := "src/test/bundles/03-local-and-remote" + + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor-all %s", bundleDir, "three"), " ") + _, _, err := e2e.UDS(cmd...) + require.NoError(t, err) + + cmd = strings.Split("zarf tools kubectl get deployment -n podinfo-flavor podinfo -o=jsonpath='{.spec.template.spec.containers[0].image}'", " ") + ref, _, err := e2e.UDS(cmd...) + require.Contains(t, ref, "ghcr.io/stefanprodan/podinfo:6.6.3") + require.NoError(t, err) + + cmd = strings.Split("zarf tools kubectl delete ns podinfo nginx zarf podinfo-flavor", " ") + _, _, err = e2e.UDS(cmd...) + require.NoError(t, err) + }) + + t.Run("Test dev deploy with flavors and force create", func(t *testing.T) { + + bundleDir := "src/test/bundles/03-local-and-remote" + + // create flavor three podinfo-flavor package + cmd = strings.Split("zarf package create src/test/packages/podinfo --flavor three", " ") + + // dev deploy with flavor two and --force-create + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create", bundleDir, "podinfo=two"), " ") + _, _, err := e2e.UDS(cmd...) + require.NoError(t, err) + + cmd = strings.Split("zarf tools kubectl get deployment -n podinfo-flavor podinfo -o=jsonpath='{.spec.template.spec.containers[0].image}'", " ") + ref, _, err := e2e.UDS(cmd...) + // assert that podinfo package with flavor two was deployed. + require.Contains(t, ref, "ghcr.io/stefanprodan/podinfo:6.6.2") + require.NoError(t, err) + + cmd = strings.Split("zarf tools kubectl delete ns podinfo nginx zarf podinfo-flavor", " ") + _, _, err = e2e.UDS(cmd...) + require.NoError(t, err) + }) } diff --git a/src/test/packages/podinfo/zarf.yaml b/src/test/packages/podinfo/zarf.yaml index 80bd123a..9d06b9c9 100644 --- a/src/test/packages/podinfo/zarf.yaml +++ b/src/test/packages/podinfo/zarf.yaml @@ -23,3 +23,47 @@ components: name: podinfo namespace: podinfo condition: available + + - name: podinfo-flavor + required: true + only: + flavor: two + charts: + - name: podinfo + version: 6.6.2 + namespace: podinfo-flavor + url: https://github.com/stefanprodan/podinfo.git + gitPath: charts/podinfo + images: + - ghcr.io/stefanprodan/podinfo:6.6.2 + actions: + onDeploy: + after: + - wait: + cluster: + kind: deployment + name: podinfo + namespace: podinfo-flavor + condition: available + + - name: podinfo-flavor + required: true + only: + flavor: three + charts: + - name: podinfo + version: 6.6.3 + namespace: podinfo-flavor + url: https://github.com/stefanprodan/podinfo.git + gitPath: charts/podinfo + images: + - ghcr.io/stefanprodan/podinfo:6.6.3 + actions: + onDeploy: + after: + - wait: + cluster: + kind: deployment + name: podinfo + namespace: podinfo-flavor + condition: available diff --git a/src/types/options.go b/src/types/options.go index d80d8dc0..4a51af41 100644 --- a/src/types/options.go +++ b/src/types/options.go @@ -6,12 +6,13 @@ package types // BundleConfig is the main struct that the bundler uses to hold high-level options. type BundleConfig struct { - CreateOpts BundleCreateOptions - DeployOpts BundleDeployOptions - PublishOpts BundlePublishOptions - PullOpts BundlePullOptions - InspectOpts BundleInspectOptions - RemoveOpts BundleRemoveOptions + CreateOpts BundleCreateOptions + DeployOpts BundleDeployOptions + PublishOpts BundlePublishOptions + PullOpts BundlePullOptions + InspectOpts BundleInspectOptions + RemoveOpts BundleRemoveOptions + DevDeployOpts BundleDevDeployOptions } // BundleCreateOptions is the options for the bundler.Create() function @@ -21,7 +22,6 @@ type BundleCreateOptions struct { SigningKeyPath string SigningKeyPassword string BundleFile string - Flavors map[string]string } // BundleDeployOptions is the options for the bundler.Deploy() function @@ -29,7 +29,6 @@ type BundleDeployOptions struct { Resume bool Source string Packages []string - Refs map[string]string PublicKeyPath string SetVariables map[string]string `json:"setVariables" jsonschema:"description=Key-Value map of variable names and their corresponding values that will be used by Zarf packages in a bundle"` // Variables and SharedVariables are read in from uds-config.yaml @@ -74,6 +73,14 @@ type BundleCommonOptions struct { OCIConcurrency int `jsonschema:"description=Number of concurrent layer operations to perform when interacting with a remote package"` } +// BundleDevDeployOptions are the options for when doing a dev deploy +type BundleDevDeployOptions struct { + Flavor map[string]string + FlavorAll string + ForceCreate bool + Ref map[string]string +} + // PathMap is a map of either absolute paths to relative paths or relative paths to absolute paths // used to map filenames during local bundle tarball creation type PathMap map[string]string From c2ff9b15f16606ed77af2725bf85eebf13473588 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Sun, 26 May 2024 12:11:38 -0600 Subject: [PATCH 03/30] add test yamls --- src/test/packages/nginx/refs/deployment.yaml | 19 +++++++++++++ src/test/packages/nginx/refs/zarf.yaml | 28 ++++++++++++++++++++ src/test/packages/podinfo/refs/zarf.yaml | 25 +++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 src/test/packages/nginx/refs/deployment.yaml create mode 100644 src/test/packages/nginx/refs/zarf.yaml create mode 100644 src/test/packages/podinfo/refs/zarf.yaml diff --git a/src/test/packages/nginx/refs/deployment.yaml b/src/test/packages/nginx/refs/deployment.yaml new file mode 100644 index 00000000..30bd1048 --- /dev/null +++ b/src/test/packages/nginx/refs/deployment.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 2 # tells deployment to run 2 pods matching the template + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.26.0 + ports: + - containerPort: 80 diff --git a/src/test/packages/nginx/refs/zarf.yaml b/src/test/packages/nginx/refs/zarf.yaml new file mode 100644 index 00000000..5677a14e --- /dev/null +++ b/src/test/packages/nginx/refs/zarf.yaml @@ -0,0 +1,28 @@ +kind: ZarfPackageConfig +metadata: + name: nginx + version: 0.0.2 + +components: + - name: nginx-remote + required: true + manifests: + - name: simple-nginx-deployment + namespace: nginx + files: + - deployment.yaml + actions: + onDeploy: + # the following checks were computed by viewing the success state of the package deployment + # and creating `wait` actions that match + after: + - wait: + cluster: + kind: deployment + name: nginx-deployment + namespace: nginx + condition: available + # image discovery is supported in all manifests and charts using: + # zarf prepare find-images + images: + - docker.io/library/nginx:1.26.0 diff --git a/src/test/packages/podinfo/refs/zarf.yaml b/src/test/packages/podinfo/refs/zarf.yaml new file mode 100644 index 00000000..da4b39a7 --- /dev/null +++ b/src/test/packages/podinfo/refs/zarf.yaml @@ -0,0 +1,25 @@ +kind: ZarfPackageConfig +metadata: + name: podinfo + version: 0.0.2 + +components: + - name: podinfo + required: true + charts: + - name: podinfo + version: 6.6.2 + namespace: podinfo + url: https://github.com/stefanprodan/podinfo.git + gitPath: charts/podinfo + images: + - ghcr.io/stefanprodan/podinfo:6.6.2 + actions: + onDeploy: + after: + - wait: + cluster: + kind: deployment + name: podinfo + namespace: podinfo + condition: available From b0e7afef1c10c861f78f7fc1ecf8f4bf68f562b8 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Sun, 26 May 2024 12:29:51 -0600 Subject: [PATCH 04/30] schema update and fix flavor tag typo in test --- src/pkg/bundle/create.go | 2 +- src/pkg/bundler/localbundle.go | 2 +- src/test/e2e/dev_test.go | 6 +++--- uds.schema.json | 4 ++++ 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/pkg/bundle/create.go b/src/pkg/bundle/create.go index 9a4dddde..92ce5988 100644 --- a/src/pkg/bundle/create.go +++ b/src/pkg/bundle/create.go @@ -85,7 +85,7 @@ func (b *Bundle) Create() error { } } - // update package refs for dev deploy + // update package ref for dev deploy if config.Dev { if len(b.cfg.DevDeployOpts.Ref) != 0 { for i, pkg := range b.bundle.Packages { diff --git a/src/pkg/bundler/localbundle.go b/src/pkg/bundler/localbundle.go index dfb61519..505aacf1 100644 --- a/src/pkg/bundler/localbundle.go +++ b/src/pkg/bundler/localbundle.go @@ -65,7 +65,7 @@ func (lo *LocalBundle) create(signature []byte) error { message.HeaderInfof("🐕 Fetching Packages") - // create root manifest for bundle, will populate with refs to uds-bundle.yaml and zarf image manifests + // create root manifest for bundle, will populate with ref to uds-bundle.yaml and zarf image manifests rootManifest := ocispec.Manifest{ MediaType: ocispec.MediaTypeImageManifest, } diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index d040172d..9fce973d 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -68,11 +68,11 @@ func TestDevDeploy(t *testing.T) { require.NoError(t, err) }) - t.Run("Test dev deploy with flavors flag", func(t *testing.T) { + t.Run("Test dev deploy with flavor flag", func(t *testing.T) { bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavors %s", bundleDir, "podinfo=three"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s", bundleDir, "podinfo=three"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) @@ -103,7 +103,7 @@ func TestDevDeploy(t *testing.T) { require.NoError(t, err) }) - t.Run("Test dev deploy with flavors and force create", func(t *testing.T) { + t.Run("Test dev deploy with flavor and force create", func(t *testing.T) { bundleDir := "src/test/bundles/03-local-and-remote" diff --git a/uds.schema.json b/uds.schema.json index 1030a301..d17a844c 100644 --- a/uds.schema.json +++ b/uds.schema.json @@ -132,6 +132,10 @@ "type": "string", "description": "Ref (tag) of the Zarf package" }, + "flavor": { + "type": "string", + "description": "Flavor of the Zarf package" + }, "optionalComponents": { "items": { "type": "string" From 7b56d2994ba7575d1917b7b1f604e3c8ba621cad Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Mon, 27 May 2024 14:01:05 -0600 Subject: [PATCH 05/30] delete debug ci yml --- src/test/e2e/dev_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index 9fce973d..ec051d0c 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -51,7 +51,7 @@ func TestDevDeploy(t *testing.T) { }) t.Run("Test dev deploy with ref flag", func(t *testing.T) { - + e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") bundleDir := "src/test/bundles/03-local-and-remote" cmd := strings.Split(fmt.Sprintf("dev deploy %s --ref %s", bundleDir, "nginx=0.0.2"), " ") @@ -69,7 +69,7 @@ func TestDevDeploy(t *testing.T) { }) t.Run("Test dev deploy with flavor flag", func(t *testing.T) { - + e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") bundleDir := "src/test/bundles/03-local-and-remote" cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s", bundleDir, "podinfo=three"), " ") @@ -86,7 +86,7 @@ func TestDevDeploy(t *testing.T) { require.NoError(t, err) }) t.Run("Test dev deploy with global flavor", func(t *testing.T) { - + e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") bundleDir := "src/test/bundles/03-local-and-remote" cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor-all %s", bundleDir, "three"), " ") From ae513bb442cfd8ad575432126bf1e2c907ebc625 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Wed, 29 May 2024 16:31:13 -0600 Subject: [PATCH 06/30] moves ref check from create to deploy --- src/cmd/dev.go | 1 + src/config/config.go | 3 +++ src/pkg/bundle/create.go | 10 ---------- src/pkg/bundle/deploy.go | 7 ++++++- src/pkg/sources/remote.go | 20 +++++++++++++++++++- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/cmd/dev.go b/src/cmd/dev.go index 1832237a..efbfe406 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -26,6 +26,7 @@ var devDeployCmd = &cobra.Command{ Long: lang.CmdDevDeployLong, Run: func(_ *cobra.Command, args []string) { config.Dev = true + config.DevDeployRefs = bundleCfg.DevDeployOpts.Ref // Get bundle source src := "" diff --git a/src/config/config.go b/src/config/config.go index a03d3ac9..7c600666 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -77,6 +77,9 @@ var ( // Dev specifies if we are running in dev mode Dev = false + + // Map of refs specified for dev deploy + DevDeployRefs map[string]string ) // GetArch returns the arch based on a priority list with options for overriding. diff --git a/src/pkg/bundle/create.go b/src/pkg/bundle/create.go index 92ce5988..1e559870 100644 --- a/src/pkg/bundle/create.go +++ b/src/pkg/bundle/create.go @@ -85,16 +85,6 @@ func (b *Bundle) Create() error { } } - // update package ref for dev deploy - if config.Dev { - if len(b.cfg.DevDeployOpts.Ref) != 0 { - for i, pkg := range b.bundle.Packages { - pkg = b.setPackageRef(pkg) - b.bundle.Packages[i] = pkg - } - } - } - opts := bundler.Options{ Bundle: &b.bundle, Output: b.cfg.CreateOpts.Output, diff --git a/src/pkg/bundle/deploy.go b/src/pkg/bundle/deploy.go index e953791d..5412c10c 100644 --- a/src/pkg/bundle/deploy.go +++ b/src/pkg/bundle/deploy.go @@ -78,7 +78,12 @@ func deployPackages(packages []types.Package, resume bool, b *Bundle) error { } // deploy each package - for _, pkg := range packagesToDeploy { + for i, pkg := range packagesToDeploy { + // update package ref for dev deploy + if config.Dev { + pkg = b.setPackageRef(pkg) + b.bundle.Packages[i] = pkg + } sha := strings.Split(pkg.Ref, "@sha256:")[1] // using appended SHA from create! pkgTmp, err := utils.MakeTempDir(config.CommonOptions.TempDirectory) if err != nil { diff --git a/src/pkg/sources/remote.go b/src/pkg/sources/remote.go index 7dc30537..63e4704b 100644 --- a/src/pkg/sources/remote.go +++ b/src/pkg/sources/remote.go @@ -42,7 +42,25 @@ type RemoteBundle struct { // LoadPackage loads a Zarf package from a remote bundle func (r *RemoteBundle) LoadPackage(dst *layout.PackagePaths, filter filters.ComponentFilterStrategy, unarchiveAll bool) (zarfTypes.ZarfPackage, []string, error) { // todo: progress bar?? - layers, err := r.downloadPkgFromRemoteBundle() + var layers []ocispec.Descriptor + var err error + + if config.Dev { + if _, ok := config.DevDeployRefs[r.Pkg.Name]; ok { + // create new oras remote for package + platform := ocispec.Platform{ + Architecture: config.GetArch(), + OS: oci.MultiOS, + } + // get remote client + repoUrl := fmt.Sprintf("%s:%s", r.Pkg.Repository, r.Pkg.Ref) + remote, _ := zoci.NewRemote(repoUrl, platform) + layers, err = remote.PullPackage(context.TODO(), r.TmpDir, config.CommonOptions.OCIConcurrency) + } + } else { + layers, err = r.downloadPkgFromRemoteBundle() + } + if err != nil { return zarfTypes.ZarfPackage{}, nil, err } From 65bfb5a7caaa80e01f10b1ef8fe4dd0826ada623 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Thu, 30 May 2024 15:01:14 -0600 Subject: [PATCH 07/30] testing updates --- src/pkg/bundle/create.go | 10 ++++++++++ src/pkg/bundle/deploy.go | 4 ++-- src/pkg/sources/remote.go | 2 ++ src/test/e2e/dev_test.go | 13 +++++++++---- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/pkg/bundle/create.go b/src/pkg/bundle/create.go index 1e559870..0248fc1f 100644 --- a/src/pkg/bundle/create.go +++ b/src/pkg/bundle/create.go @@ -85,6 +85,16 @@ func (b *Bundle) Create() error { } } + // for dev mode update package ref for local bundles, refs for remote bundles updated on deploy + if config.Dev { + if len(b.cfg.DevDeployOpts.Ref) != 0 { + for i, pkg := range b.bundle.Packages { + pkg = b.setPackageRef(pkg) + b.bundle.Packages[i] = pkg + } + } + } + opts := bundler.Options{ Bundle: &b.bundle, Output: b.cfg.CreateOpts.Output, diff --git a/src/pkg/bundle/deploy.go b/src/pkg/bundle/deploy.go index 5412c10c..8b020d4d 100644 --- a/src/pkg/bundle/deploy.go +++ b/src/pkg/bundle/deploy.go @@ -79,8 +79,8 @@ func deployPackages(packages []types.Package, resume bool, b *Bundle) error { // deploy each package for i, pkg := range packagesToDeploy { - // update package ref for dev deploy - if config.Dev { + // for dev mode update package ref for remote bundles, refs for local bundles updated on create + if config.Dev && !strings.Contains(b.cfg.DeployOpts.Source, "tar.zst") { pkg = b.setPackageRef(pkg) b.bundle.Packages[i] = pkg } diff --git a/src/pkg/sources/remote.go b/src/pkg/sources/remote.go index 63e4704b..f949634c 100644 --- a/src/pkg/sources/remote.go +++ b/src/pkg/sources/remote.go @@ -56,6 +56,8 @@ func (r *RemoteBundle) LoadPackage(dst *layout.PackagePaths, filter filters.Comp repoUrl := fmt.Sprintf("%s:%s", r.Pkg.Repository, r.Pkg.Ref) remote, _ := zoci.NewRemote(repoUrl, platform) layers, err = remote.PullPackage(context.TODO(), r.TmpDir, config.CommonOptions.OCIConcurrency) + } else { + layers, err = r.downloadPkgFromRemoteBundle() } } else { layers, err = r.downloadPkgFromRemoteBundle() diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index a60610d5..0ee669b2 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -16,7 +16,6 @@ import ( func TestDevDeploy(t *testing.T) { removeZarfInit() - cmd := strings.Split("zarf tools kubectl get deployments -A -o=jsonpath='{.items[*].metadata.name}'", " ") t.Run("Test dev deploy with local and remote pkgs", func(t *testing.T) { @@ -27,6 +26,7 @@ func TestDevDeploy(t *testing.T) { devDeploy(t, bundleDir) + cmd := strings.Split("zarf tools kubectl get deployments -A -o=jsonpath='{.items[*].metadata.name}'", " ") deployments, _, _ := e2e.UDS(cmd...) require.Contains(t, deployments, "podinfo") require.Contains(t, deployments, "nginx") @@ -43,6 +43,7 @@ func TestDevDeploy(t *testing.T) { devDeployPackages(t, bundleDir, "podinfo") + cmd := strings.Split("zarf tools kubectl get deployments -A -o=jsonpath='{.items[*].metadata.name}'", " ") deployments, _, _ := e2e.UDS(cmd...) require.Contains(t, deployments, "podinfo") require.NotContains(t, deployments, "nginx") @@ -108,11 +109,14 @@ func TestDevDeploy(t *testing.T) { bundleDir := "src/test/bundles/03-local-and-remote" // create flavor three podinfo-flavor package - cmd = strings.Split("zarf package create src/test/packages/podinfo --flavor three", " ") + pkgDir := "src/test/packages/podinfo" + cmd := strings.Split(fmt.Sprintf("zarf package create %s --flavor %s --confirm -o %s", pkgDir, "three", pkgDir), " ") + _, _, err := e2e.UDS(cmd...) + require.NoError(t, err) // dev deploy with flavor two and --force-create - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create", bundleDir, "podinfo=two"), " ") - _, _, err := e2e.UDS(cmd...) + cmd = strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create", bundleDir, "podinfo-flavor=two"), " ") + _, _, err = e2e.UDS(cmd...) require.NoError(t, err) cmd = strings.Split("zarf tools kubectl get deployment -n podinfo-flavor podinfo -o=jsonpath='{.spec.template.spec.containers[0].image}'", " ") @@ -131,6 +135,7 @@ func TestDevDeploy(t *testing.T) { devDeploy(t, bundle) + cmd := strings.Split("zarf tools kubectl get deployments -A -o=jsonpath='{.items[*].metadata.name}'", " ") deployments, _, _ := e2e.UDS(cmd...) require.Contains(t, deployments, "podinfo") require.Contains(t, deployments, "nginx") From fed1aec872715c7408477723394fe0cf4f73a254 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Thu, 30 May 2024 16:54:44 -0600 Subject: [PATCH 08/30] fix flavor test --- src/test/e2e/dev_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index 0ee669b2..4d438a4a 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -115,7 +115,7 @@ func TestDevDeploy(t *testing.T) { require.NoError(t, err) // dev deploy with flavor two and --force-create - cmd = strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create", bundleDir, "podinfo-flavor=two"), " ") + cmd = strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create", bundleDir, "podinfo=two"), " ") _, _, err = e2e.UDS(cmd...) require.NoError(t, err) From 70895517d536d4db85e3f5ac82b1efd660219a74 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Fri, 31 May 2024 15:37:43 -0600 Subject: [PATCH 09/30] update documentation --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f1679521..da9024ad 100644 --- a/README.md +++ b/README.md @@ -288,7 +288,9 @@ The `dev deploy` command performs the following operations - If local bundle: Creates Zarf packages for all local packages in a bundle - Creates the Zarf tarball in the same directory as the `zarf.yaml` - - Will only create the Zarf tarball if one does not already exist + - Can use `--flavor` and `--flavor-all` flags to specify what flavor of package you want to create + - Will only create the Zarf tarball if one does not already exist or can use `--force-create` to force the creation of a new zarf package even if one currently exists - Ignores any `kind: ZarfInitConfig` packages in the bundle - Creates a bundle from the newly created Zarf packages - Deploys the bundle in [YOLO](https://docs.zarf.dev/faq/#what-is-yolo-mode-and-why-would-i-use-it) mode, eliminating the need to do a `zarf init` +- For remote packages you can specify what package ref you want to deploy by using the `--ref` flag and specifying the package name and desired ref. (example: `--ref podinfo=0.2.0`) From 672df73d9d2ff489093860b38607ed828d08a96e Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Mon, 3 Jun 2024 11:11:46 -0600 Subject: [PATCH 10/30] fix error messaging --- src/cmd/dev.go | 33 +++++++++++++++++++++++++++++---- src/pkg/bundle/create.go | 8 ++++++-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/cmd/dev.go b/src/cmd/dev.go index 9941b35d..4435b51a 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -5,6 +5,9 @@ package cmd import ( + "fmt" + "strings" + "github.com/defenseunicorns/pkg/helpers/v2" "github.com/defenseunicorns/uds-cli/src/config" "github.com/defenseunicorns/uds-cli/src/config/lang" @@ -35,9 +38,15 @@ var devDeployCmd = &cobra.Command{ } // Check if source is a local bundle - localBundle := helpers.IsDir(src) + isLocalBundle := isLocalBundle(src) + + // Validate flags + err := validateDevDeployFlags(isLocalBundle) + if err != nil { + message.Fatalf(err, "Failed to validate flags: %s", err.Error()) + } - if localBundle { + if isLocalBundle { // Create Bundle setBundleFile(args) @@ -59,7 +68,7 @@ var devDeployCmd = &cobra.Command{ defer bndlClient.ClearPaths() // Create dev bundle - if localBundle { + if isLocalBundle { // Check if local zarf packages need to be created bndlClient.CreateZarfPkgs() @@ -69,7 +78,7 @@ var devDeployCmd = &cobra.Command{ } // Set dev source - if localBundle { + if isLocalBundle { bndlClient.SetDeploySource(src) } else { bundleCfg.DeployOpts.Source = src @@ -80,6 +89,22 @@ var devDeployCmd = &cobra.Command{ }, } +// isLocalBundle checks if the bundle source is a local bundle +func isLocalBundle(src string) bool { + return helpers.IsDir(src) || strings.Contains(src, ".tar.zst") +} + +// validateDevDeployFlags validates the flags for dev deploy +func validateDevDeployFlags(isLocalBundle bool) error { + if !isLocalBundle { + //Throw error if trying to run with --flavor, --flavor-all, or --force-create flag with remote bundle + if len(bundleCfg.DevDeployOpts.Flavor) > 0 || bundleCfg.DevDeployOpts.FlavorAll != "" || bundleCfg.DevDeployOpts.ForceCreate { + return fmt.Errorf("Cannot use --flavor, --flavor-all, or --force-create flags with remote bundle") + } + } + return nil +} + func init() { initViper() rootCmd.AddCommand(devCmd) diff --git a/src/pkg/bundle/create.go b/src/pkg/bundle/create.go index 0248fc1f..3f9ebc33 100644 --- a/src/pkg/bundle/create.go +++ b/src/pkg/bundle/create.go @@ -109,6 +109,8 @@ func (b *Bundle) Create() error { func (b *Bundle) setPackageRef(pkg types.Package) types.Package { if ref, ok := b.cfg.DevDeployOpts.Ref[pkg.Name]; ok { pkg.Ref = ref + errMsg := fmt.Sprintf("Unable to access %s:%s", pkg.Repository, pkg.Ref) + // Get SHA from registry url := fmt.Sprintf("%s:%s", pkg.Repository, pkg.Ref) @@ -118,14 +120,16 @@ func (b *Bundle) setPackageRef(pkg types.Package) types.Package { } remote, err := zoci.NewRemote(url, platform) if err != nil { - message.Fatalf(err, "Unable to access %s:%s", pkg.Repository, pkg.Ref) + message.Fatalf(err, errMsg) } if err := remote.Repo().Reference.ValidateReferenceAsDigest(); err != nil { manifestDesc, err := remote.ResolveRoot(context.TODO()) if err != nil { - message.Fatalf(err, "Unable to access %s:%s", pkg.Repository, pkg.Ref) + message.Fatalf(err, errMsg) } pkg.Ref = pkg.Ref + "@sha256:" + manifestDesc.Digest.Encoded() + } else { + message.Fatalf(err, errMsg) } } return pkg From 5273a77fdcfa184ebd60ee710c700d0cb1d747ab Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Mon, 3 Jun 2024 15:30:05 -0600 Subject: [PATCH 11/30] addressing pr comments --- src/pkg/bundle/create.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/pkg/bundle/create.go b/src/pkg/bundle/create.go index 3f9ebc33..ffe9b8ee 100644 --- a/src/pkg/bundle/create.go +++ b/src/pkg/bundle/create.go @@ -86,12 +86,10 @@ func (b *Bundle) Create() error { } // for dev mode update package ref for local bundles, refs for remote bundles updated on deploy - if config.Dev { - if len(b.cfg.DevDeployOpts.Ref) != 0 { - for i, pkg := range b.bundle.Packages { - pkg = b.setPackageRef(pkg) - b.bundle.Packages[i] = pkg - } + if config.Dev && len(b.cfg.DevDeployOpts.Ref) != 0 { + for i, pkg := range b.bundle.Packages { + pkg = b.setPackageRef(pkg) + b.bundle.Packages[i] = pkg } } From 6951177c55ea5e15a4a73233e52b967df9fa5629 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Mon, 3 Jun 2024 20:46:03 -0600 Subject: [PATCH 12/30] consolidate flavor and flavor-all flags --- README.md | 2 +- src/cmd/dev.go | 31 +++++++++++-- src/cmd/dev_test.go | 99 ++++++++++++++++++++++++++++++++++++++++ src/config/lang/lang.go | 1 - src/pkg/bundle/dev.go | 6 +-- src/test/e2e/dev_test.go | 3 +- src/types/options.go | 2 +- 7 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 src/cmd/dev_test.go diff --git a/README.md b/README.md index da9024ad..bc16138c 100644 --- a/README.md +++ b/README.md @@ -288,7 +288,7 @@ The `dev deploy` command performs the following operations - If local bundle: Creates Zarf packages for all local packages in a bundle - Creates the Zarf tarball in the same directory as the `zarf.yaml` - - Can use `--flavor` and `--flavor-all` flags to specify what flavor of package you want to create + - Can use `--flavor` flag to specify what flavor of package you want to create - Will only create the Zarf tarball if one does not already exist or can use `--force-create` to force the creation of a new zarf package even if one currently exists - Ignores any `kind: ZarfInitConfig` packages in the bundle - Creates a bundle from the newly created Zarf packages diff --git a/src/cmd/dev.go b/src/cmd/dev.go index 4435b51a..657c0d43 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -47,6 +47,9 @@ var devDeployCmd = &cobra.Command{ } if isLocalBundle { + // Populate flavor map + populateFlavorMap() + // Create Bundle setBundleFile(args) @@ -97,22 +100,40 @@ func isLocalBundle(src string) bool { // validateDevDeployFlags validates the flags for dev deploy func validateDevDeployFlags(isLocalBundle bool) error { if !isLocalBundle { - //Throw error if trying to run with --flavor, --flavor-all, or --force-create flag with remote bundle - if len(bundleCfg.DevDeployOpts.Flavor) > 0 || bundleCfg.DevDeployOpts.FlavorAll != "" || bundleCfg.DevDeployOpts.ForceCreate { - return fmt.Errorf("Cannot use --flavor, --flavor-all, or --force-create flags with remote bundle") + //Throw error if trying to run with --flavor or --force-create flag with remote bundle + if len(bundleCfg.DevDeployOpts.Flavor) > 0 || bundleCfg.DevDeployOpts.ForceCreate { + return fmt.Errorf("Cannot use --flavor or --force-create flags with remote bundle") } } return nil } +// populateFlavorMap populates the flavor map based on the string input to the --flavor flag +func populateFlavorMap() { + if bundleCfg.DevDeployOpts.FlavorInput != "" { + flavorEntries := strings.Split(bundleCfg.DevDeployOpts.FlavorInput, ",") + for _, entry := range flavorEntries { + entrySplit := strings.Split(entry, "=") + if len(entrySplit) != 2 { + if len(entrySplit) == 1 { + bundleCfg.DevDeployOpts.Flavor = map[string]string{"": bundleCfg.DevDeployOpts.FlavorInput} + } else { + message.Fatalf(nil, "Invalid flavor entry: %s", entry) + } + } else { + bundleCfg.DevDeployOpts.Flavor[entrySplit[0]] = entrySplit[1] + } + } + } +} + func init() { initViper() rootCmd.AddCommand(devCmd) devCmd.AddCommand(devDeployCmd) devDeployCmd.Flags().StringArrayVarP(&bundleCfg.DeployOpts.Packages, "packages", "p", []string{}, lang.CmdBundleDeployFlagPackages) devDeployCmd.Flags().StringToStringVarP(&bundleCfg.DevDeployOpts.Ref, "ref", "r", map[string]string{}, lang.CmdBundleDeployFlagRef) - devDeployCmd.Flags().StringToStringVarP(&bundleCfg.DevDeployOpts.Flavor, "flavor", "f", map[string]string{}, lang.CmdBundleCreateFlagFlavor) - devDeployCmd.Flags().StringVar(&bundleCfg.DevDeployOpts.FlavorAll, "flavor-all", "", lang.CmdBundleCreateFlagFlavorAll) + devDeployCmd.Flags().StringVarP(&bundleCfg.DevDeployOpts.FlavorInput, "flavor", "f", "", lang.CmdBundleCreateFlagFlavor) devDeployCmd.Flags().BoolVar(&bundleCfg.DevDeployOpts.ForceCreate, "force-create", false, lang.CmdBundleCreateForceCreate) devDeployCmd.Flags().BoolVarP(&config.CommonOptions.Confirm, "confirm", "c", false, lang.CmdBundleDeployFlagConfirm) devDeployCmd.Flags().StringToStringVar(&bundleCfg.DeployOpts.SetVariables, "set", nil, lang.CmdBundleDeployFlagSet) diff --git a/src/cmd/dev_test.go b/src/cmd/dev_test.go new file mode 100644 index 00000000..7e209ff0 --- /dev/null +++ b/src/cmd/dev_test.go @@ -0,0 +1,99 @@ +package cmd + +import ( + "testing" + + "github.com/defenseunicorns/uds-cli/src/types" + "github.com/stretchr/testify/assert" +) + +func TestValidateDevDeployFlags(t *testing.T) { + testCases := []struct { + name string + localBundle bool + DevDeployOpts types.BundleDevDeployOptions + expectError bool + }{ + { + name: "Local bundle with --ref flag", + localBundle: true, + DevDeployOpts: types.BundleDevDeployOptions{ + Ref: map[string]string{"some-key": "some-ref"}, + }, + expectError: true, + }, + { + name: "Remote bundle with --ref flag", + localBundle: false, + DevDeployOpts: types.BundleDevDeployOptions{ + Ref: map[string]string{"some-key": "some-ref"}, + }, + expectError: false, + }, + { + name: "Local bundle with --flavor flag", + localBundle: true, + DevDeployOpts: types.BundleDevDeployOptions{ + Flavor: map[string]string{"some-key": "some-flavor"}, + }, + expectError: false, + }, + { + name: "Remote bundle with --flavor flag", + localBundle: false, + DevDeployOpts: types.BundleDevDeployOptions{ + Flavor: map[string]string{"some-key": "some-flavor"}, + }, + expectError: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + bundleCfg.DevDeployOpts = tc.DevDeployOpts + + err := validateDevDeployFlags(tc.localBundle) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestIsLocalBundle(t *testing.T) { + testCases := []struct { + name string + src string + want bool + }{ + { + name: "Test with directory", + src: "../cmd/", + want: true, + }, + { + name: "Test with .tar.zst file", + src: "/path/to/file.tar.zst", + want: true, + }, + { + name: "Test with other file", + src: "/path/to/file.txt", + want: false, + }, + { + name: "Test with registry", + src: "ghcr.io/defenseunicorns/uds-cli/nginx", + want: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := isLocalBundle(tc.src) + assert.Equal(t, tc.want, got) + }) + } +} diff --git a/src/config/lang/lang.go b/src/config/lang/lang.go index 6377f525..32d43b34 100644 --- a/src/config/lang/lang.go +++ b/src/config/lang/lang.go @@ -30,7 +30,6 @@ const ( CmdBundleCreateFlagSigningKey = "Path to private key file for signing bundles" CmdBundleCreateFlagSigningKeyPassword = "Password to the private key file used for signing bundles" CmdBundleCreateFlagFlavor = "Specify which zarf package flavor you want to use." - CmdBundleCreateFlagFlavorAll = "Specify which zarf package flavor you want to use for all packages in the bundle" // bundle deploy CmdBundleDeployShort = "Deploy a bundle from a local tarball or oci:// URL" diff --git a/src/pkg/bundle/dev.go b/src/pkg/bundle/dev.go index bb49ef76..2a9023dd 100644 --- a/src/pkg/bundle/dev.go +++ b/src/pkg/bundle/dev.go @@ -50,7 +50,7 @@ func (b *Bundle) CreateZarfPkgs() { } // create local zarf package if it doesn't exist if !packageFound || b.cfg.DevDeployOpts.ForceCreate { - if len(b.cfg.DevDeployOpts.Flavor) != 0 || b.cfg.DevDeployOpts.FlavorAll != "" { + if len(b.cfg.DevDeployOpts.Flavor) != 0 { b.setPackageFlavor(&pkg) os.Args = []string{"zarf", "package", "create", pkgDir, "--confirm", "-o", pkgDir, "--skip-sbom", "--flavor", pkg.Flavor} } else { @@ -67,8 +67,8 @@ func (b *Bundle) CreateZarfPkgs() { func (b *Bundle) setPackageFlavor(pkg *types.Package) { // handle case when flavor applies to all packages - if b.cfg.DevDeployOpts.FlavorAll != "" { - pkg.Flavor = b.cfg.DevDeployOpts.FlavorAll + if len(b.cfg.DevDeployOpts.Flavor) == 1 && b.cfg.DevDeployOpts.Flavor[""] != "" { + pkg.Flavor = b.cfg.DevDeployOpts.Flavor[""] } else if flavor, ok := b.cfg.DevDeployOpts.Flavor[pkg.Name]; ok { pkg.Flavor = flavor } diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index 4d438a4a..102e02df 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -87,10 +87,9 @@ func TestDevDeploy(t *testing.T) { require.NoError(t, err) }) t.Run("Test dev deploy with global flavor", func(t *testing.T) { - e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor-all %s", bundleDir, "three"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create -l=debug", bundleDir, "three"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) diff --git a/src/types/options.go b/src/types/options.go index e01ee99b..d9b8593f 100644 --- a/src/types/options.go +++ b/src/types/options.go @@ -76,8 +76,8 @@ type BundleCommonOptions struct { // BundleDevDeployOptions are the options for when doing a dev deploy type BundleDevDeployOptions struct { + FlavorInput string Flavor map[string]string - FlavorAll string ForceCreate bool Ref map[string]string } From fdfa4cb3e3e4414475f396d1de7155de0f0e49d8 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Mon, 3 Jun 2024 21:10:00 -0600 Subject: [PATCH 13/30] fix flavor bug --- src/cmd/dev.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/dev.go b/src/cmd/dev.go index 657c0d43..27a50c5b 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -111,6 +111,7 @@ func validateDevDeployFlags(isLocalBundle bool) error { // populateFlavorMap populates the flavor map based on the string input to the --flavor flag func populateFlavorMap() { if bundleCfg.DevDeployOpts.FlavorInput != "" { + bundleCfg.DevDeployOpts.Flavor = make(map[string]string) flavorEntries := strings.Split(bundleCfg.DevDeployOpts.FlavorInput, ",") for _, entry := range flavorEntries { entrySplit := strings.Split(entry, "=") From 17b7724cd53d118eb68a4785ad00d63db3d69cae Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Mon, 3 Jun 2024 21:23:13 -0600 Subject: [PATCH 14/30] refactor to remove DevDeployRefs from config --- src/cmd/dev.go | 1 - src/config/config.go | 3 --- src/pkg/bundle/deploy.go | 2 +- src/pkg/bundle/remove.go | 2 +- src/pkg/sources/new.go | 13 ++++++++++++- src/pkg/sources/remote.go | 3 ++- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/cmd/dev.go b/src/cmd/dev.go index 27a50c5b..89320e46 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -29,7 +29,6 @@ var devDeployCmd = &cobra.Command{ Long: lang.CmdDevDeployLong, Run: func(_ *cobra.Command, args []string) { config.Dev = true - config.DevDeployRefs = bundleCfg.DevDeployOpts.Ref // Get bundle source src := "" diff --git a/src/config/config.go b/src/config/config.go index 7c600666..a03d3ac9 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -77,9 +77,6 @@ var ( // Dev specifies if we are running in dev mode Dev = false - - // Map of refs specified for dev deploy - DevDeployRefs map[string]string ) // GetArch returns the arch based on a priority list with options for overriding. diff --git a/src/pkg/bundle/deploy.go b/src/pkg/bundle/deploy.go index bc6bdac5..4ebc19ca 100644 --- a/src/pkg/bundle/deploy.go +++ b/src/pkg/bundle/deploy.go @@ -130,7 +130,7 @@ func deployPackages(packages []types.Package, resume bool, b *Bundle) error { // Automatically confirm the package deployment zarfConfig.CommonOptions.Confirm = true - source, err := sources.New(b.cfg.DeployOpts.Source, pkg, opts, sha, nsOverrides) + source, err := sources.New(*b.cfg, pkg, opts, sha, nsOverrides) if err != nil { return err } diff --git a/src/pkg/bundle/remove.go b/src/pkg/bundle/remove.go index a6768064..8a7f0f52 100644 --- a/src/pkg/bundle/remove.go +++ b/src/pkg/bundle/remove.go @@ -94,7 +94,7 @@ func removePackages(packagesToRemove []types.Package, b *Bundle) error { } sha := strings.Split(pkg.Ref, "sha256:")[1] - source, err := sources.New(b.cfg.RemoveOpts.Source, pkg, opts, sha, nil) + source, err := sources.New(*b.cfg, pkg, opts, sha, nil) if err != nil { return err } diff --git a/src/pkg/sources/new.go b/src/pkg/sources/new.go index 8c902772..2000f531 100644 --- a/src/pkg/sources/new.go +++ b/src/pkg/sources/new.go @@ -5,6 +5,7 @@ package sources import ( + "fmt" "strings" "github.com/defenseunicorns/pkg/oci" @@ -17,8 +18,17 @@ import ( ) // New creates a new package source based on pkgLocation -func New(pkgLocation string, pkg types.Package, opts zarfTypes.ZarfPackageOptions, sha string, nsOverrides NamespaceOverrideMap) (zarfSources.PackageSource, error) { +func New(bundleCfg types.BundleConfig, pkg types.Package, opts zarfTypes.ZarfPackageOptions, sha string, nsOverrides NamespaceOverrideMap) (zarfSources.PackageSource, error) { var source zarfSources.PackageSource + var pkgLocation string + if bundleCfg.DeployOpts.Source != "" { + pkgLocation = bundleCfg.DeployOpts.Source + } else if bundleCfg.RemoveOpts.Source != "" { + pkgLocation = bundleCfg.DeployOpts.Source + } else { + return nil, fmt.Errorf("no source provided for package %s", pkg.Name) + } + if strings.Contains(pkgLocation, "tar.zst") { source = &TarballBundle{ Pkg: pkg, @@ -44,6 +54,7 @@ func New(pkgLocation string, pkg types.Package, opts zarfTypes.ZarfPackageOption TmpDir: opts.PackageSource, Remote: remote.OrasRemote, nsOverrides: nsOverrides, + bundleCfg: bundleCfg, } } return source, nil diff --git a/src/pkg/sources/remote.go b/src/pkg/sources/remote.go index f949634c..8cfc0755 100644 --- a/src/pkg/sources/remote.go +++ b/src/pkg/sources/remote.go @@ -37,6 +37,7 @@ type RemoteBundle struct { TmpDir string Remote *oci.OrasRemote nsOverrides NamespaceOverrideMap + bundleCfg types.BundleConfig } // LoadPackage loads a Zarf package from a remote bundle @@ -46,7 +47,7 @@ func (r *RemoteBundle) LoadPackage(dst *layout.PackagePaths, filter filters.Comp var err error if config.Dev { - if _, ok := config.DevDeployRefs[r.Pkg.Name]; ok { + if _, ok := r.bundleCfg.DevDeployOpts.Ref[r.Pkg.Name]; ok { // create new oras remote for package platform := ocispec.Platform{ Architecture: config.GetArch(), From a365356e669e872e895ccfce084240ac4111528e Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Mon, 3 Jun 2024 21:34:57 -0600 Subject: [PATCH 15/30] fix bug regarding RemoveOpts.source --- src/pkg/sources/new.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/sources/new.go b/src/pkg/sources/new.go index 2000f531..56681e49 100644 --- a/src/pkg/sources/new.go +++ b/src/pkg/sources/new.go @@ -24,7 +24,7 @@ func New(bundleCfg types.BundleConfig, pkg types.Package, opts zarfTypes.ZarfPac if bundleCfg.DeployOpts.Source != "" { pkgLocation = bundleCfg.DeployOpts.Source } else if bundleCfg.RemoveOpts.Source != "" { - pkgLocation = bundleCfg.DeployOpts.Source + pkgLocation = bundleCfg.RemoveOpts.Source } else { return nil, fmt.Errorf("no source provided for package %s", pkg.Name) } From 50c4c24c752603f306b965de51cb9b9adf70df64 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Tue, 4 Jun 2024 11:32:54 -0600 Subject: [PATCH 16/30] adding unit tests and confirmation on all bundle types --- src/cmd/dev.go | 20 +++++++++--------- src/cmd/dev_test.go | 51 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/cmd/dev.go b/src/cmd/dev.go index 89320e46..33bacf96 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -47,12 +47,14 @@ var devDeployCmd = &cobra.Command{ if isLocalBundle { // Populate flavor map - populateFlavorMap() + err = populateFlavorMap() + if err != nil { + message.Fatalf(err, "Failed to populate flavor map: %s", err.Error()) + } // Create Bundle setBundleFile(args) - config.CommonOptions.Confirm = true bundleCfg.CreateOpts.SourceDirectory = src } @@ -77,10 +79,6 @@ var devDeployCmd = &cobra.Command{ if err := bndlClient.Create(); err != nil { message.Fatalf(err, "Failed to create bundle: %s", err.Error()) } - } - - // Set dev source - if isLocalBundle { bndlClient.SetDeploySource(src) } else { bundleCfg.DeployOpts.Source = src @@ -108,23 +106,25 @@ func validateDevDeployFlags(isLocalBundle bool) error { } // populateFlavorMap populates the flavor map based on the string input to the --flavor flag -func populateFlavorMap() { +func populateFlavorMap() error { if bundleCfg.DevDeployOpts.FlavorInput != "" { bundleCfg.DevDeployOpts.Flavor = make(map[string]string) flavorEntries := strings.Split(bundleCfg.DevDeployOpts.FlavorInput, ",") - for _, entry := range flavorEntries { + for i, entry := range flavorEntries { entrySplit := strings.Split(entry, "=") if len(entrySplit) != 2 { - if len(entrySplit) == 1 { + // check i==0 to check for invalid input (ex. key=value1,value2) + if len(entrySplit) == 1 && i == 0 { bundleCfg.DevDeployOpts.Flavor = map[string]string{"": bundleCfg.DevDeployOpts.FlavorInput} } else { - message.Fatalf(nil, "Invalid flavor entry: %s", entry) + return fmt.Errorf("Invalid flavor entry: %s", entry) } } else { bundleCfg.DevDeployOpts.Flavor[entrySplit[0]] = entrySplit[1] } } } + return nil } func init() { diff --git a/src/cmd/dev_test.go b/src/cmd/dev_test.go index 7e209ff0..0a60ae99 100644 --- a/src/cmd/dev_test.go +++ b/src/cmd/dev_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/defenseunicorns/uds-cli/src/types" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestValidateDevDeployFlags(t *testing.T) { @@ -54,9 +54,9 @@ func TestValidateDevDeployFlags(t *testing.T) { err := validateDevDeployFlags(tc.localBundle) if tc.expectError { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -93,7 +93,50 @@ func TestIsLocalBundle(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { got := isLocalBundle(tc.src) - assert.Equal(t, tc.want, got) + require.Equal(t, tc.want, got) + }) + } +} + +func TestPopulateFlavorMap(t *testing.T) { + testCases := []struct { + name string + FlavorInput string + expect map[string]string + expectError bool + }{ + { + name: "Test with valid flavor input", + FlavorInput: "key1=value1,key2=value2", + expect: map[string]string{"key1": "value1", "key2": "value2"}, + }, + { + name: "Test with single value", + FlavorInput: "value1", + expect: map[string]string{"": "value1"}, + }, + { + name: "Test with invalid flavor input", + FlavorInput: "key1=value1,key2", + expectError: true, + }, + { + name: "Test with empty flavor input", + FlavorInput: "", + expect: nil, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + bundleCfg.DevDeployOpts.FlavorInput = tc.FlavorInput + bundleCfg.DevDeployOpts.Flavor = nil + err := populateFlavorMap() + if tc.expectError { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.expect, bundleCfg.DevDeployOpts.Flavor) + } }) } } From 4f05eff5167ca96ae89d8255be058316cfd86820 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Tue, 4 Jun 2024 12:47:14 -0600 Subject: [PATCH 17/30] review updates --- src/pkg/bundle/common.go | 29 +++++++++++++++++++++++++++++ src/pkg/bundle/create.go | 33 --------------------------------- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/pkg/bundle/common.go b/src/pkg/bundle/common.go index c1f31791..b5b8a064 100644 --- a/src/pkg/bundle/common.go +++ b/src/pkg/bundle/common.go @@ -344,3 +344,32 @@ func validateBundleVars(packages []types.Package) error { } return nil } + +// setPackageRef sets the package reference +func (b *Bundle) setPackageRef(pkg types.Package) types.Package { + if ref, ok := b.cfg.DevDeployOpts.Ref[pkg.Name]; ok { + errMsg := fmt.Sprintf("Unable to access %s:%s", pkg.Repository, ref) + + // Get SHA from registry + url := fmt.Sprintf("%s:%s", pkg.Repository, ref) + + platform := ocispec.Platform{ + Architecture: config.GetArch(), + OS: oci.MultiOS, + } + remote, err := zoci.NewRemote(url, platform) + if err != nil { + message.Fatalf(err, errMsg) + } + if err := remote.Repo().Reference.ValidateReferenceAsDigest(); err != nil { + manifestDesc, err := remote.ResolveRoot(context.TODO()) + if err != nil { + message.Fatalf(err, errMsg) + } + pkg.Ref = ref + "@sha256:" + manifestDesc.Digest.Encoded() + } else { + message.Fatalf(err, errMsg) + } + } + return pkg +} diff --git a/src/pkg/bundle/create.go b/src/pkg/bundle/create.go index ffe9b8ee..1f506750 100644 --- a/src/pkg/bundle/create.go +++ b/src/pkg/bundle/create.go @@ -5,12 +5,10 @@ package bundle import ( - "context" "fmt" "path/filepath" "github.com/AlecAivazis/survey/v2" - "github.com/defenseunicorns/pkg/oci" "github.com/defenseunicorns/uds-cli/src/config" "github.com/defenseunicorns/uds-cli/src/pkg/bundler" "github.com/defenseunicorns/uds-cli/src/pkg/utils" @@ -19,8 +17,6 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/interactive" "github.com/defenseunicorns/zarf/src/pkg/message" zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils" - "github.com/defenseunicorns/zarf/src/pkg/zoci" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pterm/pterm" "helm.sh/helm/v3/pkg/chartutil" ) @@ -104,35 +100,6 @@ func (b *Bundle) Create() error { return bundlerClient.Create() } -func (b *Bundle) setPackageRef(pkg types.Package) types.Package { - if ref, ok := b.cfg.DevDeployOpts.Ref[pkg.Name]; ok { - pkg.Ref = ref - errMsg := fmt.Sprintf("Unable to access %s:%s", pkg.Repository, pkg.Ref) - - // Get SHA from registry - url := fmt.Sprintf("%s:%s", pkg.Repository, pkg.Ref) - - platform := ocispec.Platform{ - Architecture: config.GetArch(), - OS: oci.MultiOS, - } - remote, err := zoci.NewRemote(url, platform) - if err != nil { - message.Fatalf(err, errMsg) - } - if err := remote.Repo().Reference.ValidateReferenceAsDigest(); err != nil { - manifestDesc, err := remote.ResolveRoot(context.TODO()) - if err != nil { - message.Fatalf(err, errMsg) - } - pkg.Ref = pkg.Ref + "@sha256:" + manifestDesc.Digest.Encoded() - } else { - message.Fatalf(err, errMsg) - } - } - return pkg -} - // confirmBundleCreation prompts the user to confirm bundle creation func (b *Bundle) confirmBundleCreation() (confirm bool) { From 858463c7a4f87fec8ee23908523d1ef7e9ddbf1d Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Tue, 4 Jun 2024 20:39:30 -0600 Subject: [PATCH 18/30] add test fixes this time --- src/pkg/bundle/dev.go | 10 +++++----- src/test/e2e/dev_test.go | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/pkg/bundle/dev.go b/src/pkg/bundle/dev.go index 2a9023dd..23809ee4 100644 --- a/src/pkg/bundle/dev.go +++ b/src/pkg/bundle/dev.go @@ -27,8 +27,7 @@ func (b *Bundle) CreateZarfPkgs() { } zarfPackagePattern := `^zarf-.*\.tar\.zst$` - for i := range b.bundle.Packages { - pkg := b.bundle.Packages[i] + for _, pkg := range b.bundle.Packages { // if pkg is a local zarf package, attempt to create it if it doesn't exist if pkg.Path != "" { path := getPkgPath(pkg, config.GetArch(b.bundle.Metadata.Architecture), srcDir) @@ -51,7 +50,7 @@ func (b *Bundle) CreateZarfPkgs() { // create local zarf package if it doesn't exist if !packageFound || b.cfg.DevDeployOpts.ForceCreate { if len(b.cfg.DevDeployOpts.Flavor) != 0 { - b.setPackageFlavor(&pkg) + pkg = b.setPackageFlavor(pkg) os.Args = []string{"zarf", "package", "create", pkgDir, "--confirm", "-o", pkgDir, "--skip-sbom", "--flavor", pkg.Flavor} } else { os.Args = []string{"zarf", "package", "create", pkgDir, "--confirm", "-o", pkgDir, "--skip-sbom"} @@ -65,13 +64,14 @@ func (b *Bundle) CreateZarfPkgs() { } } -func (b *Bundle) setPackageFlavor(pkg *types.Package) { - // handle case when flavor applies to all packages +func (b *Bundle) setPackageFlavor(pkg types.Package) types.Package { + // handle case when flavor applies to all packages, which is specified by an empty key in DevDeployOpts.Flavor if len(b.cfg.DevDeployOpts.Flavor) == 1 && b.cfg.DevDeployOpts.Flavor[""] != "" { pkg.Flavor = b.cfg.DevDeployOpts.Flavor[""] } else if flavor, ok := b.cfg.DevDeployOpts.Flavor[pkg.Name]; ok { pkg.Flavor = flavor } + return pkg } // SetDeploySource sets the source for the bundle when in dev mode diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index 102e02df..9d3f0b87 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -55,7 +55,7 @@ func TestDevDeploy(t *testing.T) { e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --ref %s", bundleDir, "nginx=0.0.2"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --ref %s --confirm", bundleDir, "nginx=0.0.2"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) @@ -73,7 +73,7 @@ func TestDevDeploy(t *testing.T) { e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s", bundleDir, "podinfo=three"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --confirm", bundleDir, "podinfo=three"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) @@ -89,7 +89,7 @@ func TestDevDeploy(t *testing.T) { t.Run("Test dev deploy with global flavor", func(t *testing.T) { bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create -l=debug", bundleDir, "three"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "three"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) @@ -114,7 +114,7 @@ func TestDevDeploy(t *testing.T) { require.NoError(t, err) // dev deploy with flavor two and --force-create - cmd = strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create", bundleDir, "podinfo=two"), " ") + cmd = strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "podinfo=two"), " ") _, _, err = e2e.UDS(cmd...) require.NoError(t, err) From 7982151622498ec51d3e46db827c28d4aa4a4a55 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Tue, 4 Jun 2024 20:55:38 -0600 Subject: [PATCH 19/30] test fix --- src/test/e2e/commands_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/e2e/commands_test.go b/src/test/e2e/commands_test.go index cda25a57..479ff875 100644 --- a/src/test/e2e/commands_test.go +++ b/src/test/e2e/commands_test.go @@ -126,7 +126,7 @@ func devDeploy(t *testing.T, bundlePath string) (stdout string, stderr string) { } func devDeployPackages(t *testing.T, tarballPath string, packages string) (stdout string, stderr string) { - cmd := strings.Split(fmt.Sprintf("dev deploy %s --packages %s", tarballPath, packages), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --packages %s --confirm", tarballPath, packages), " ") stdout, stderr, err := e2e.UDS(cmd...) require.NoError(t, err) return stdout, stderr From ebedfacd28839968c8bf5258a4201d91704ff1a8 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Wed, 5 Jun 2024 12:37:50 -0600 Subject: [PATCH 20/30] remove extra space causing test to fail... smh --- src/test/e2e/dev_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index 9d3f0b87..2088b9d1 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -89,7 +89,7 @@ func TestDevDeploy(t *testing.T) { t.Run("Test dev deploy with global flavor", func(t *testing.T) { bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "three"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "three"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) From ee0b2e9153a0e275550140817f7bfa887a6e9281 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Wed, 5 Jun 2024 13:15:29 -0600 Subject: [PATCH 21/30] clarity is kindness --- src/pkg/bundle/dev.go | 3 ++- src/test/e2e/dev_test.go | 14 +++++++------- src/test/packages/nginx/refs/zarf.yaml | 1 + src/test/packages/podinfo/refs/zarf.yaml | 2 ++ src/test/packages/podinfo/zarf.yaml | 4 ++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/pkg/bundle/dev.go b/src/pkg/bundle/dev.go index 23809ee4..f8e85904 100644 --- a/src/pkg/bundle/dev.go +++ b/src/pkg/bundle/dev.go @@ -65,7 +65,8 @@ func (b *Bundle) CreateZarfPkgs() { } func (b *Bundle) setPackageFlavor(pkg types.Package) types.Package { - // handle case when flavor applies to all packages, which is specified by an empty key in DevDeployOpts.Flavor + // handle case when --flavor flag applies to all packages + // empty key references a value that is applied to all package flavors if len(b.cfg.DevDeployOpts.Flavor) == 1 && b.cfg.DevDeployOpts.Flavor[""] != "" { pkg.Flavor = b.cfg.DevDeployOpts.Flavor[""] } else if flavor, ok := b.cfg.DevDeployOpts.Flavor[pkg.Name]; ok { diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index 2088b9d1..85f8a19f 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -73,7 +73,7 @@ func TestDevDeploy(t *testing.T) { e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --confirm", bundleDir, "podinfo=three"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --confirm", bundleDir, "podinfo=patchVersion3"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) @@ -89,7 +89,7 @@ func TestDevDeploy(t *testing.T) { t.Run("Test dev deploy with global flavor", func(t *testing.T) { bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "three"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "patchVersion3"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) @@ -107,20 +107,20 @@ func TestDevDeploy(t *testing.T) { bundleDir := "src/test/bundles/03-local-and-remote" - // create flavor three podinfo-flavor package + // create flavor patchVersion3 podinfo-flavor package pkgDir := "src/test/packages/podinfo" - cmd := strings.Split(fmt.Sprintf("zarf package create %s --flavor %s --confirm -o %s", pkgDir, "three", pkgDir), " ") + cmd := strings.Split(fmt.Sprintf("zarf package create %s --flavor %s --confirm -o %s", pkgDir, "patchVersion3", pkgDir), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) - // dev deploy with flavor two and --force-create - cmd = strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "podinfo=two"), " ") + // dev deploy with flavor patchVersion2 and --force-create + cmd = strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "podinfo=patchVersion2"), " ") _, _, err = e2e.UDS(cmd...) require.NoError(t, err) cmd = strings.Split("zarf tools kubectl get deployment -n podinfo-flavor podinfo -o=jsonpath='{.spec.template.spec.containers[0].image}'", " ") ref, _, err := e2e.UDS(cmd...) - // assert that podinfo package with flavor two was deployed. + // assert that podinfo package with flavor patchVersion2 was deployed. require.Contains(t, ref, "ghcr.io/stefanprodan/podinfo:6.6.2") require.NoError(t, err) diff --git a/src/test/packages/nginx/refs/zarf.yaml b/src/test/packages/nginx/refs/zarf.yaml index 5677a14e..6982cd7f 100644 --- a/src/test/packages/nginx/refs/zarf.yaml +++ b/src/test/packages/nginx/refs/zarf.yaml @@ -2,6 +2,7 @@ kind: ZarfPackageConfig metadata: name: nginx version: 0.0.2 + description: nginx deployment using image docker.io/library/nginx:1.26.0 for testing dev deploy --refs flag components: - name: nginx-remote diff --git a/src/test/packages/podinfo/refs/zarf.yaml b/src/test/packages/podinfo/refs/zarf.yaml index da4b39a7..691a3647 100644 --- a/src/test/packages/podinfo/refs/zarf.yaml +++ b/src/test/packages/podinfo/refs/zarf.yaml @@ -2,6 +2,8 @@ kind: ZarfPackageConfig metadata: name: podinfo version: 0.0.2 + description: podinfo deployment using image ghcr.io/stefanprodan/podinfo:6.6.2 for testing dev deploy --refs flag + components: - name: podinfo diff --git a/src/test/packages/podinfo/zarf.yaml b/src/test/packages/podinfo/zarf.yaml index 9d06b9c9..ef9f21da 100644 --- a/src/test/packages/podinfo/zarf.yaml +++ b/src/test/packages/podinfo/zarf.yaml @@ -27,7 +27,7 @@ components: - name: podinfo-flavor required: true only: - flavor: two + flavor: patchVersion2 charts: - name: podinfo version: 6.6.2 @@ -49,7 +49,7 @@ components: - name: podinfo-flavor required: true only: - flavor: three + flavor: patchVersion3 charts: - name: podinfo version: 6.6.3 From 35e5b9fada216edc26af745660aab033ec0c5235 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Wed, 5 Jun 2024 19:50:22 -0600 Subject: [PATCH 22/30] fullsend no more confirm, update hack/push-test-artifacts.sh --- hack/push-test-artifacts.sh | 8 +++++++- src/cmd/dev.go | 2 +- src/test/e2e/dev_test.go | 10 +++++----- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/hack/push-test-artifacts.sh b/hack/push-test-artifacts.sh index 23c465ac..731875b1 100755 --- a/hack/push-test-artifacts.sh +++ b/hack/push-test-artifacts.sh @@ -12,8 +12,14 @@ set -e cd ./../src/test/packages/nginx zarf package create -o oci://ghcr.io/defenseunicorns/uds-cli --confirm -a amd64 zarf package create -o oci://ghcr.io/defenseunicorns/uds-cli --confirm -a arm64 +cd ./refs +zarf package create -o oci://ghcr.io/defenseunicorns/uds-cli --confirm -a amd64 +zarf package create -o oci://ghcr.io/defenseunicorns/uds-cli --confirm -a arm64 -cd ../podinfo +cd ../../podinfo +zarf package create -o oci://ghcr.io/defenseunicorns/uds-cli --confirm -a amd64 +zarf package create -o oci://ghcr.io/defenseunicorns/uds-cli --confirm -a arm64 +cd ./refs zarf package create -o oci://ghcr.io/defenseunicorns/uds-cli --confirm -a amd64 zarf package create -o oci://ghcr.io/defenseunicorns/uds-cli --confirm -a arm64 diff --git a/src/cmd/dev.go b/src/cmd/dev.go index 33bacf96..3fd5fdc3 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -29,6 +29,7 @@ var devDeployCmd = &cobra.Command{ Long: lang.CmdDevDeployLong, Run: func(_ *cobra.Command, args []string) { config.Dev = true + config.CommonOptions.Confirm = true // Get bundle source src := "" @@ -135,6 +136,5 @@ func init() { devDeployCmd.Flags().StringToStringVarP(&bundleCfg.DevDeployOpts.Ref, "ref", "r", map[string]string{}, lang.CmdBundleDeployFlagRef) devDeployCmd.Flags().StringVarP(&bundleCfg.DevDeployOpts.FlavorInput, "flavor", "f", "", lang.CmdBundleCreateFlagFlavor) devDeployCmd.Flags().BoolVar(&bundleCfg.DevDeployOpts.ForceCreate, "force-create", false, lang.CmdBundleCreateForceCreate) - devDeployCmd.Flags().BoolVarP(&config.CommonOptions.Confirm, "confirm", "c", false, lang.CmdBundleDeployFlagConfirm) devDeployCmd.Flags().StringToStringVar(&bundleCfg.DeployOpts.SetVariables, "set", nil, lang.CmdBundleDeployFlagSet) } diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index 85f8a19f..cc0cfb50 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -55,7 +55,7 @@ func TestDevDeploy(t *testing.T) { e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --ref %s --confirm", bundleDir, "nginx=0.0.2"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --ref %s", bundleDir, "nginx=0.0.2"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) @@ -73,7 +73,7 @@ func TestDevDeploy(t *testing.T) { e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --confirm", bundleDir, "podinfo=patchVersion3"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s", bundleDir, "podinfo=patchVersion3"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) @@ -89,7 +89,7 @@ func TestDevDeploy(t *testing.T) { t.Run("Test dev deploy with global flavor", func(t *testing.T) { bundleDir := "src/test/bundles/03-local-and-remote" - cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "patchVersion3"), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create", bundleDir, "patchVersion3"), " ") _, _, err := e2e.UDS(cmd...) require.NoError(t, err) @@ -114,7 +114,7 @@ func TestDevDeploy(t *testing.T) { require.NoError(t, err) // dev deploy with flavor patchVersion2 and --force-create - cmd = strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create --confirm", bundleDir, "podinfo=patchVersion2"), " ") + cmd = strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create", bundleDir, "podinfo=patchVersion2"), " ") _, _, err = e2e.UDS(cmd...) require.NoError(t, err) @@ -145,7 +145,7 @@ func TestDevDeploy(t *testing.T) { t.Run("Test dev deploy with --set flag", func(t *testing.T) { bundleDir := "src/test/bundles/02-variables" bundleTarballPath := filepath.Join(bundleDir, fmt.Sprintf("uds-bundle-variables-%s-0.0.1.tar.zst", e2e.Arch)) - _, stderr := runCmd(t, "dev deploy "+bundleDir+" --set ANIMAL=Longhorns --set COUNTRY=Texas --confirm -l=debug") + _, stderr := runCmd(t, "dev deploy "+bundleDir+" --set ANIMAL=Longhorns --set COUNTRY=Texas -l=debug") require.Contains(t, stderr, "This fun-fact was imported: Longhorns are the national animal of Texas") require.NotContains(t, stderr, "This fun-fact was imported: Unicorns are the national animal of Scotland") remove(t, bundleTarballPath) From 5c9b865fb1d59c04c8f5d52c0fdc322e57ccff1e Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Wed, 5 Jun 2024 19:56:00 -0600 Subject: [PATCH 23/30] fullersend --- src/test/e2e/commands_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/e2e/commands_test.go b/src/test/e2e/commands_test.go index 479ff875..d93564e8 100644 --- a/src/test/e2e/commands_test.go +++ b/src/test/e2e/commands_test.go @@ -119,14 +119,14 @@ func deploy(t *testing.T, tarballPath string) (stdout string, stderr string) { } func devDeploy(t *testing.T, bundlePath string) (stdout string, stderr string) { - cmd := strings.Split(fmt.Sprintf("dev deploy %s --confirm", bundlePath), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s", bundlePath), " ") stdout, stderr, err := e2e.UDS(cmd...) require.NoError(t, err) return stdout, stderr } func devDeployPackages(t *testing.T, tarballPath string, packages string) (stdout string, stderr string) { - cmd := strings.Split(fmt.Sprintf("dev deploy %s --packages %s --confirm", tarballPath, packages), " ") + cmd := strings.Split(fmt.Sprintf("dev deploy %s --packages %s", tarballPath, packages), " ") stdout, stderr, err := e2e.UDS(cmd...) require.NoError(t, err) return stdout, stderr From 9d7202667a396105375fe1ac8b3642483a65559a Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Thu, 6 Jun 2024 11:20:50 -0600 Subject: [PATCH 24/30] add error messaging for ref and flavor flags on incompatible sources --- src/config/lang/lang.go | 2 +- src/pkg/bundle/common.go | 5 +++++ src/pkg/bundle/dev.go | 10 ++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/config/lang/lang.go b/src/config/lang/lang.go index 32d43b34..6cc99299 100644 --- a/src/config/lang/lang.go +++ b/src/config/lang/lang.go @@ -83,7 +83,7 @@ const ( CmdZarfShort = "Run a zarf command" // uds dev - CmdDevShort = "Commands useful for developing bundles" + CmdDevShort = "[beta] Commands useful for developing bundles" CmdDevDeployShort = "[beta] Creates and deploys a UDS bundle from a given directory in dev mode" CmdDevDeployLong = "[beta] Creates and deploys a UDS bundle from a given directory in dev mode, setting package options like YOLO mode for faster iteration." CmdBundleCreateForceCreate = "For local bundles with local packages, specify whether to create a zarf package even if it already exists." diff --git a/src/pkg/bundle/common.go b/src/pkg/bundle/common.go index b5b8a064..9467ea5e 100644 --- a/src/pkg/bundle/common.go +++ b/src/pkg/bundle/common.go @@ -348,6 +348,11 @@ func validateBundleVars(packages []types.Package) error { // setPackageRef sets the package reference func (b *Bundle) setPackageRef(pkg types.Package) types.Package { if ref, ok := b.cfg.DevDeployOpts.Ref[pkg.Name]; ok { + // Can only set refs for remote packages + if pkg.Repository == "" { + message.Fatalf(errors.New("Invalid input"), "Cannot set ref for local packages: %s", pkg.Name) + } + errMsg := fmt.Sprintf("Unable to access %s:%s", pkg.Repository, ref) // Get SHA from registry diff --git a/src/pkg/bundle/dev.go b/src/pkg/bundle/dev.go index f8e85904..0b969fd9 100644 --- a/src/pkg/bundle/dev.go +++ b/src/pkg/bundle/dev.go @@ -5,6 +5,7 @@ package bundle import ( + "errors" "fmt" "os" "path/filepath" @@ -28,6 +29,15 @@ func (b *Bundle) CreateZarfPkgs() { zarfPackagePattern := `^zarf-.*\.tar\.zst$` for _, pkg := range b.bundle.Packages { + // Can only set flavors for local packages + if pkg.Path == "" { + // check if attempting to apply flavor to remote package + if (len(b.cfg.DevDeployOpts.Flavor) == 1 && b.cfg.DevDeployOpts.Flavor[""] != "") || + (b.cfg.DevDeployOpts.Flavor[pkg.Name] != "") { + message.Fatalf(errors.New("Invalid input"), "Cannot set flavor for remote packages: %s", pkg.Name) + } + } + // if pkg is a local zarf package, attempt to create it if it doesn't exist if pkg.Path != "" { path := getPkgPath(pkg, config.GetArch(b.bundle.Metadata.Architecture), srcDir) From 102e0993601db8bf689103d657fad713cd6e46d6 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Thu, 6 Jun 2024 11:54:13 -0600 Subject: [PATCH 25/30] split up bundles and packages for flavor tests --- .../bundles/15-dev-deploy/uds-bundle.yaml | 10 ++++ src/test/e2e/dev_test.go | 14 +++--- src/test/packages/podinfo/flavors/zarf.yaml | 49 +++++++++++++++++++ src/test/packages/podinfo/zarf.yaml | 44 ----------------- 4 files changed, 66 insertions(+), 51 deletions(-) create mode 100644 src/test/bundles/15-dev-deploy/uds-bundle.yaml create mode 100644 src/test/packages/podinfo/flavors/zarf.yaml diff --git a/src/test/bundles/15-dev-deploy/uds-bundle.yaml b/src/test/bundles/15-dev-deploy/uds-bundle.yaml new file mode 100644 index 00000000..5d980e3e --- /dev/null +++ b/src/test/bundles/15-dev-deploy/uds-bundle.yaml @@ -0,0 +1,10 @@ +kind: UDSBundle +metadata: + name: dev-deploy-flavors + description: building from a local Zarf pkg with flavors + version: 0.0.1 + +packages: + - name: podinfo + path: "../../packages/podinfo/flavors" + ref: 0.0.1 diff --git a/src/test/e2e/dev_test.go b/src/test/e2e/dev_test.go index cc0cfb50..e9a14798 100644 --- a/src/test/e2e/dev_test.go +++ b/src/test/e2e/dev_test.go @@ -70,8 +70,8 @@ func TestDevDeploy(t *testing.T) { }) t.Run("Test dev deploy with flavor flag", func(t *testing.T) { - e2e.DeleteZarfPkg(t, "src/test/packages/podinfo") - bundleDir := "src/test/bundles/03-local-and-remote" + e2e.DeleteZarfPkg(t, "src/test/packages/podinfo/flavors") + bundleDir := "src/test/bundles/15-dev-deploy" cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s", bundleDir, "podinfo=patchVersion3"), " ") _, _, err := e2e.UDS(cmd...) @@ -82,12 +82,12 @@ func TestDevDeploy(t *testing.T) { require.Contains(t, ref, "ghcr.io/stefanprodan/podinfo:6.6.3") require.NoError(t, err) - cmd = strings.Split("zarf tools kubectl delete ns podinfo nginx zarf podinfo-flavor", " ") + cmd = strings.Split("zarf tools kubectl delete ns zarf podinfo-flavor", " ") _, _, err = e2e.UDS(cmd...) require.NoError(t, err) }) t.Run("Test dev deploy with global flavor", func(t *testing.T) { - bundleDir := "src/test/bundles/03-local-and-remote" + bundleDir := "src/test/bundles/15-dev-deploy" cmd := strings.Split(fmt.Sprintf("dev deploy %s --flavor %s --force-create", bundleDir, "patchVersion3"), " ") _, _, err := e2e.UDS(cmd...) @@ -98,14 +98,14 @@ func TestDevDeploy(t *testing.T) { require.Contains(t, ref, "ghcr.io/stefanprodan/podinfo:6.6.3") require.NoError(t, err) - cmd = strings.Split("zarf tools kubectl delete ns podinfo nginx zarf podinfo-flavor", " ") + cmd = strings.Split("zarf tools kubectl delete ns zarf podinfo-flavor", " ") _, _, err = e2e.UDS(cmd...) require.NoError(t, err) }) t.Run("Test dev deploy with flavor and force create", func(t *testing.T) { - bundleDir := "src/test/bundles/03-local-and-remote" + bundleDir := "src/test/bundles/15-dev-deploy" // create flavor patchVersion3 podinfo-flavor package pkgDir := "src/test/packages/podinfo" @@ -124,7 +124,7 @@ func TestDevDeploy(t *testing.T) { require.Contains(t, ref, "ghcr.io/stefanprodan/podinfo:6.6.2") require.NoError(t, err) - cmd = strings.Split("zarf tools kubectl delete ns podinfo nginx zarf podinfo-flavor", " ") + cmd = strings.Split("zarf tools kubectl delete ns zarf podinfo-flavor", " ") _, _, err = e2e.UDS(cmd...) require.NoError(t, err) }) diff --git a/src/test/packages/podinfo/flavors/zarf.yaml b/src/test/packages/podinfo/flavors/zarf.yaml new file mode 100644 index 00000000..26a4de05 --- /dev/null +++ b/src/test/packages/podinfo/flavors/zarf.yaml @@ -0,0 +1,49 @@ +kind: ZarfPackageConfig +metadata: + name: podinfo + version: 0.0.1 + +components: + - name: podinfo-flavor + required: true + only: + flavor: patchVersion2 + charts: + - name: podinfo + version: 6.6.2 + namespace: podinfo-flavor + url: https://github.com/stefanprodan/podinfo.git + gitPath: charts/podinfo + images: + - ghcr.io/stefanprodan/podinfo:6.6.2 + actions: + onDeploy: + after: + - wait: + cluster: + kind: deployment + name: podinfo + namespace: podinfo-flavor + condition: available + + - name: podinfo-flavor + required: true + only: + flavor: patchVersion3 + charts: + - name: podinfo + version: 6.6.3 + namespace: podinfo-flavor + url: https://github.com/stefanprodan/podinfo.git + gitPath: charts/podinfo + images: + - ghcr.io/stefanprodan/podinfo:6.6.3 + actions: + onDeploy: + after: + - wait: + cluster: + kind: deployment + name: podinfo + namespace: podinfo-flavor + condition: available diff --git a/src/test/packages/podinfo/zarf.yaml b/src/test/packages/podinfo/zarf.yaml index ef9f21da..80bd123a 100644 --- a/src/test/packages/podinfo/zarf.yaml +++ b/src/test/packages/podinfo/zarf.yaml @@ -23,47 +23,3 @@ components: name: podinfo namespace: podinfo condition: available - - - name: podinfo-flavor - required: true - only: - flavor: patchVersion2 - charts: - - name: podinfo - version: 6.6.2 - namespace: podinfo-flavor - url: https://github.com/stefanprodan/podinfo.git - gitPath: charts/podinfo - images: - - ghcr.io/stefanprodan/podinfo:6.6.2 - actions: - onDeploy: - after: - - wait: - cluster: - kind: deployment - name: podinfo - namespace: podinfo-flavor - condition: available - - - name: podinfo-flavor - required: true - only: - flavor: patchVersion3 - charts: - - name: podinfo - version: 6.6.3 - namespace: podinfo-flavor - url: https://github.com/stefanprodan/podinfo.git - gitPath: charts/podinfo - images: - - ghcr.io/stefanprodan/podinfo:6.6.3 - actions: - onDeploy: - after: - - wait: - cluster: - kind: deployment - name: podinfo - namespace: podinfo-flavor - condition: available From c7564a66aedef65b21bc45acce48277458498509 Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Fri, 7 Jun 2024 10:26:42 -0600 Subject: [PATCH 26/30] better docs? --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ad4a5cbb..98b375c4 100644 --- a/README.md +++ b/README.md @@ -293,8 +293,7 @@ UDS CLI includes a vendored version of Zarf inside of its binary. To use Zarf, s ## Dev Mode -> [!NOTE] -> Dev mode is a BETA feature +NOTE: Dev mode is a BETA feature Dev mode facilitates faster dev cycles when developing and testing bundles @@ -302,16 +301,17 @@ Dev mode facilitates faster dev cycles when developing and testing bundles uds dev deploy | ``` -The `dev deploy` command performs the following operations +The `dev deploy` command performs the following operations: -- If local bundle: Creates Zarf packages for all local packages in a bundle - - Creates the Zarf tarball in the same directory as the `zarf.yaml` - - Can use `--flavor` flag to specify what flavor of package you want to create - - Will only create the Zarf tarball if one does not already exist or can use `--force-create` to force the creation of a new zarf package even if one currently exists - - Ignores any `kind: ZarfInitConfig` packages in the bundle - - Creates a bundle from the newly created Zarf packages - Deploys the bundle in [YOLO](https://docs.zarf.dev/faq/#what-is-yolo-mode-and-why-would-i-use-it) mode, eliminating the need to do a `zarf init` -- For remote packages you can specify what package ref you want to deploy by using the `--ref` flag and specifying the package name and desired ref. (example: `--ref podinfo=0.2.0`) + - any `kind: ZarfInitConfig` packages in the bundle will be ignored +- For local bundles: + - Creates the Zarf tarball if one does not already exist or the `--force-create` flag can be used to force the creation of a new zarf package + - The Zarf tarball is created in the same directory as the `zarf.yaml` + - The `--flavor` flag can be used to specify what flavor of a package you want to create (example: `--flavor podinfo=upstream` to specify the flavor for the `podinfo` package or `--flavor upstream` to specify the flavor for all the packages in the bundle) + - Creates a bundle from the newly created Zarf packages +- For remote packages: + - The `--ref` flagcan be used to specify what package ref you want to deploy (example: `--ref podinfo=0.2.0`) ## Scan From e2db54ee20fb1c5aa18e4fcc805f5b52422dcef1 Mon Sep 17 00:00:00 2001 From: decleaver <85503726+decleaver@users.noreply.github.com> Date: Fri, 7 Jun 2024 12:35:13 -0600 Subject: [PATCH 27/30] Update README.md Co-authored-by: UncleGedd <42304551+UncleGedd@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98b375c4..cabfb59c 100644 --- a/README.md +++ b/README.md @@ -304,7 +304,7 @@ uds dev deploy | The `dev deploy` command performs the following operations: - Deploys the bundle in [YOLO](https://docs.zarf.dev/faq/#what-is-yolo-mode-and-why-would-i-use-it) mode, eliminating the need to do a `zarf init` - - any `kind: ZarfInitConfig` packages in the bundle will be ignored + - Any `kind: ZarfInitConfig` packages in the bundle will be ignored - For local bundles: - Creates the Zarf tarball if one does not already exist or the `--force-create` flag can be used to force the creation of a new zarf package - The Zarf tarball is created in the same directory as the `zarf.yaml` From f56e62899dfdb070be2fb84b9b8504b5fcf75096 Mon Sep 17 00:00:00 2001 From: decleaver <85503726+decleaver@users.noreply.github.com> Date: Fri, 7 Jun 2024 12:36:14 -0600 Subject: [PATCH 28/30] Update README.md Co-authored-by: UncleGedd <42304551+UncleGedd@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cabfb59c..490c45d0 100644 --- a/README.md +++ b/README.md @@ -306,7 +306,7 @@ The `dev deploy` command performs the following operations: - Deploys the bundle in [YOLO](https://docs.zarf.dev/faq/#what-is-yolo-mode-and-why-would-i-use-it) mode, eliminating the need to do a `zarf init` - Any `kind: ZarfInitConfig` packages in the bundle will be ignored - For local bundles: - - Creates the Zarf tarball if one does not already exist or the `--force-create` flag can be used to force the creation of a new zarf package + - Creates the Zarf tarball if one does not already exist or the `--force-create` flag can be used to force the creation of a new Zarf package - The Zarf tarball is created in the same directory as the `zarf.yaml` - The `--flavor` flag can be used to specify what flavor of a package you want to create (example: `--flavor podinfo=upstream` to specify the flavor for the `podinfo` package or `--flavor upstream` to specify the flavor for all the packages in the bundle) - Creates a bundle from the newly created Zarf packages From d7abcf699393a57a24b42341cacb196c82954b4e Mon Sep 17 00:00:00 2001 From: Darcy Cleaver Date: Fri, 7 Jun 2024 12:37:44 -0600 Subject: [PATCH 29/30] fix docs --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 490c45d0..69bd9963 100644 --- a/README.md +++ b/README.md @@ -306,12 +306,13 @@ The `dev deploy` command performs the following operations: - Deploys the bundle in [YOLO](https://docs.zarf.dev/faq/#what-is-yolo-mode-and-why-would-i-use-it) mode, eliminating the need to do a `zarf init` - Any `kind: ZarfInitConfig` packages in the bundle will be ignored - For local bundles: - - Creates the Zarf tarball if one does not already exist or the `--force-create` flag can be used to force the creation of a new Zarf package - - The Zarf tarball is created in the same directory as the `zarf.yaml` - - The `--flavor` flag can be used to specify what flavor of a package you want to create (example: `--flavor podinfo=upstream` to specify the flavor for the `podinfo` package or `--flavor upstream` to specify the flavor for all the packages in the bundle) + - Local Packages: + - Creates the Zarf tarball if one does not already exist or the `--force-create` flag can be used to force the creation of a new Zarf package + - The Zarf tarball is created in the same directory as the `zarf.yaml` + - The `--flavor` flag can be used to specify what flavor of a package you want to create (example: `--flavor podinfo=upstream` to specify the flavor for the `podinfo` package or `--flavor upstream` to specify the flavor for all the packages in the bundle) + - For remote packages: + - The `--ref` flag can be used to specify what package ref you want to deploy (example: `--ref podinfo=0.2.0`) - Creates a bundle from the newly created Zarf packages -- For remote packages: - - The `--ref` flagcan be used to specify what package ref you want to deploy (example: `--ref podinfo=0.2.0`) ## Scan From 97b44e02fbd95d82404d573a653dc1fa7b6259d5 Mon Sep 17 00:00:00 2001 From: decleaver <85503726+decleaver@users.noreply.github.com> Date: Fri, 7 Jun 2024 12:48:34 -0600 Subject: [PATCH 30/30] Update README.md Co-authored-by: UncleGedd <42304551+UncleGedd@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 69bd9963..84cf6536 100644 --- a/README.md +++ b/README.md @@ -306,7 +306,7 @@ The `dev deploy` command performs the following operations: - Deploys the bundle in [YOLO](https://docs.zarf.dev/faq/#what-is-yolo-mode-and-why-would-i-use-it) mode, eliminating the need to do a `zarf init` - Any `kind: ZarfInitConfig` packages in the bundle will be ignored - For local bundles: - - Local Packages: + - For local packages: - Creates the Zarf tarball if one does not already exist or the `--force-create` flag can be used to force the creation of a new Zarf package - The Zarf tarball is created in the same directory as the `zarf.yaml` - The `--flavor` flag can be used to specify what flavor of a package you want to create (example: `--flavor podinfo=upstream` to specify the flavor for the `podinfo` package or `--flavor upstream` to specify the flavor for all the packages in the bundle)