Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: dev deploy --ref and --flavor flags #638

Merged
merged 37 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4c18547
flavor and ref updates
decleaver May 21, 2024
31e6d7c
Merge branch 'main' into 537-dev-deploy-refs
decleaver May 22, 2024
8d36284
check refs and flavors on create, for local bundles
decleaver May 26, 2024
c2ff9b1
add test yamls
decleaver May 26, 2024
b0e7afe
schema update and fix flavor tag typo in test
decleaver May 26, 2024
7b56d29
delete debug ci yml
decleaver May 27, 2024
1ed528d
Merge branch 'main' into 537-dev-deploy-refs
decleaver May 29, 2024
f5aa28b
Merge branch 'main' into 537-dev-deploy-refs
decleaver May 29, 2024
ae513bb
moves ref check from create to deploy
decleaver May 29, 2024
f8e4d23
Merge branch 'main' into 537-dev-deploy-refs
decleaver May 29, 2024
65bfb5a
testing updates
decleaver May 30, 2024
fed1aec
fix flavor test
decleaver May 30, 2024
7089551
update documentation
decleaver May 31, 2024
13cbccc
Merge branch 'main' into 537-dev-deploy-refs
decleaver Jun 3, 2024
672df73
fix error messaging
decleaver Jun 3, 2024
5273a77
addressing pr comments
decleaver Jun 3, 2024
6951177
consolidate flavor and flavor-all flags
decleaver Jun 4, 2024
fdfa4cb
fix flavor bug
decleaver Jun 4, 2024
17b7724
refactor to remove DevDeployRefs from config
decleaver Jun 4, 2024
a365356
fix bug regarding RemoveOpts.source
decleaver Jun 4, 2024
50c4c24
adding unit tests and confirmation on all bundle types
decleaver Jun 4, 2024
4f05eff
review updates
decleaver Jun 4, 2024
858463c
add test fixes this time
decleaver Jun 5, 2024
7982151
test fix
decleaver Jun 5, 2024
ebedfac
remove extra space causing test to fail... smh
decleaver Jun 5, 2024
68ba0f1
Merge branch 'main' into 537-dev-deploy-refs
decleaver Jun 5, 2024
ee0b2e9
clarity is kindness
decleaver Jun 5, 2024
35e5b9f
fullsend no more confirm, update hack/push-test-artifacts.sh
decleaver Jun 6, 2024
5c9b865
fullersend
decleaver Jun 6, 2024
9d72026
add error messaging for ref and flavor flags on incompatible sources
decleaver Jun 6, 2024
102e099
split up bundles and packages for flavor tests
decleaver Jun 6, 2024
72a0d38
Merge branch 'main' into 537-dev-deploy-refs
decleaver Jun 6, 2024
c7564a6
better docs?
decleaver Jun 7, 2024
e2db54e
Update README.md
decleaver Jun 7, 2024
f56e628
Update README.md
decleaver Jun 7, 2024
d7abcf6
fix docs
decleaver Jun 7, 2024
97b44e0
Update README.md
decleaver Jun 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
38 changes: 34 additions & 4 deletions src/cmd/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -26,6 +29,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 := ""
Expand All @@ -34,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)

Expand All @@ -58,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()

Expand All @@ -68,7 +78,7 @@ var devDeployCmd = &cobra.Command{
}

// Set dev source
if localBundle {
if isLocalBundle {
decleaver marked this conversation as resolved.
Show resolved Hide resolved
bndlClient.SetDeploySource(src)
} else {
bundleCfg.DeployOpts.Source = src
Expand All @@ -79,11 +89,31 @@ 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
UncleGedd marked this conversation as resolved.
Show resolved Hide resolved
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)
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)
decleaver marked this conversation as resolved.
Show resolved Hide resolved
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)
}
3 changes: 3 additions & 0 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
decleaver marked this conversation as resolved.
Show resolved Hide resolved
)

// GetArch returns the arch based on a priority list with options for overriding.
Expand Down
10 changes: 7 additions & 3 deletions src/config/lang/lang.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +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"
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"
Expand All @@ -37,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)"
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"
Expand Down Expand Up @@ -81,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."
)
49 changes: 44 additions & 5 deletions src/pkg/bundle/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
)
Expand All @@ -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")
Expand Down Expand Up @@ -86,16 +85,56 @@ func (b *Bundle) Create() error {
}
}

// for dev mode update package ref for local bundles, refs for remote bundles updated on deploy
decleaver marked this conversation as resolved.
Show resolved Hide resolved
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,
TmpDstDir: b.tmp,
SourceDir: b.cfg.CreateOpts.SourceDirectory,
}
bundlerClient := bundler.NewBundler(&opts)

return bundlerClient.Create()
}

func (b *Bundle) setPackageRef(pkg types.Package) types.Package {
decleaver marked this conversation as resolved.
Show resolved Hide resolved
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()
decleaver marked this conversation as resolved.
Show resolved Hide resolved
} else {
message.Fatalf(err, errMsg)
}
}
return pkg
}

// confirmBundleCreation prompts the user to confirm bundle creation
func (b *Bundle) confirmBundleCreation() (confirm bool) {

Expand Down
13 changes: 9 additions & 4 deletions src/pkg/bundle/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ 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 {
packagesToDeploy = b.bundle.Packages
UncleGedd marked this conversation as resolved.
Show resolved Hide resolved
}

return deployPackages(b.bundle.Packages, resume, b)
return deployPackages(packagesToDeploy, resume, b)
}

func deployPackages(packages []types.Package, resume bool, b *Bundle) error {
Expand All @@ -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 {
// 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
}
sha := strings.Split(pkg.Ref, "@sha256:")[1] // using appended SHA from create!
pkgTmp, err := utils.MakeTempDir(config.CommonOptions.TempDirectory)
if err != nil {
Expand Down
22 changes: 19 additions & 3 deletions src/pkg/bundle/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/defenseunicorns/uds-cli/src/config"
"github.com/defenseunicorns/uds-cli/src/pkg/utils"
"github.com/defenseunicorns/uds-cli/src/types"

zarfCLI "github.com/defenseunicorns/zarf/src/cmd"
"github.com/defenseunicorns/zarf/src/pkg/message"
Expand All @@ -26,7 +27,8 @@ func (b *Bundle) CreateZarfPkgs() {
}

zarfPackagePattern := `^zarf-.*\.tar\.zst$`
for _, pkg := range b.bundle.Packages {
for i := range b.bundle.Packages {
decleaver marked this conversation as resolved.
Show resolved Hide resolved
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)
Expand All @@ -47,8 +49,13 @@ 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"}
if !packageFound || b.cfg.DevDeployOpts.ForceCreate {
if len(b.cfg.DevDeployOpts.Flavor) != 0 || b.cfg.DevDeployOpts.FlavorAll != "" {
b.setPackageFlavor(&pkg)
decleaver marked this conversation as resolved.
Show resolved Hide resolved
os.Args = []string{"zarf", "package", "create", pkgDir, "--confirm", "-o", pkgDir, "--skip-sbom", "--flavor", pkg.Flavor}
UncleGedd marked this conversation as resolved.
Show resolved Hide resolved
} 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())
Expand All @@ -58,6 +65,15 @@ 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
} else if flavor, ok := b.cfg.DevDeployOpts.Flavor[pkg.Name]; ok {
pkg.Flavor = flavor
}
}

// SetDeploySource sets the source for the bundle when in dev mode
func (b *Bundle) SetDeploySource(srcDir string) {
filename := fmt.Sprintf("%s%s-%s-%s.tar.zst", config.BundlePrefix, b.bundle.Metadata.Name, b.bundle.Metadata.Architecture, b.bundle.Metadata.Version)
Expand Down
2 changes: 1 addition & 1 deletion src/pkg/bundler/localbundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,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,
}
Expand Down
22 changes: 21 additions & 1 deletion src/pkg/sources/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,27 @@ 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()
}
} else {
layers, err = r.downloadPkgFromRemoteBundle()
}

if err != nil {
return zarfTypes.ZarfPackage{}, nil, err
}
Expand Down
Loading
Loading