diff --git a/README.md b/README.md index f1679521..a96e502b 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,16 @@ This means that setting the `--architecture` flag takes precedence over all othe UDS CLI supports multi-arch bundles. This means you can push bundles with different architectures to the same remote OCI repository, at the same tag. For example, you can push both an `amd64` and `arm64` bundle to `ghcr.io//:0.0.1`. +### Architecture Validation +When deploying a local bundle, the bundle's architecture will be used for comparison against the cluster architecture to ensure compatability. If deploying a remote bundle, by default the bundle is pulled based on system architecture, which is then checked against the cluster. + +> [!NOTE] +> It is possible to override the bundle architecture used at validation time by using the `--architecture` / `-a` flag. + +If, for example, you have a multi-arch remote bundle that you want to deploy from an arm64 machine to an amd64 cluster, the validation with fail because the system arch does not match the cluster arch. However, you can pull the correct bundle version by specificying the arch with the command line architecture flag. + +e.g. +`uds deploy -a amd64 --confirm` ## Configuration The UDS CLI can be configured with a `uds-config.yaml` file. This file can be placed in the current working directory or specified with an environment variable called `UDS_CONFIG`. The basic structure of the `uds-config.yaml` is as follows: diff --git a/src/pkg/bundle/deploy.go b/src/pkg/bundle/deploy.go index 1df17212..d75ff7e1 100644 --- a/src/pkg/bundle/deploy.go +++ b/src/pkg/bundle/deploy.go @@ -286,12 +286,6 @@ func (b *Bundle) PreDeployValidation() (string, string, string, error) { } b.cfg.DeployOpts.Source = source - // validate config's arch against cluster - err = ValidateArch(config.GetArch()) - if err != nil { - return "", "", "", err - } - // create a new provider provider, err := NewBundleProvider(b.cfg.DeployOpts.Source, b.tmp) if err != nil { @@ -321,6 +315,12 @@ func (b *Bundle) PreDeployValidation() (string, string, string, error) { return "", "", "", err } + // validate bundle's arch against cluster + err = ValidateArch(config.GetArch(b.bundle.Build.Architecture)) + if err != nil { + return "", "", "", err + } + bundleName := b.bundle.Metadata.Name return bundleName, string(bundleYAML), source, err } diff --git a/src/test/common.go b/src/test/common.go index cf527278..dd846335 100644 --- a/src/test/common.go +++ b/src/test/common.go @@ -180,6 +180,21 @@ func (e2e *UDSE2ETest) CreateZarfPkg(t *testing.T, path string, forceCreate bool require.NoError(t, err) } +// CreateZarfPkgWithArch creates a Zarf package of a user specified arch in the given path +func (e2e *UDSE2ETest) CreateZarfPkgWithArch(t *testing.T, path string, forceCreate bool, arch string) { + // check if pkg already exists + pattern := fmt.Sprintf("%s/*-%s-*.tar.zst", path, arch) + matches, err := filepath.Glob(pattern) + require.NoError(t, err) + if !forceCreate && len(matches) > 0 { + fmt.Println("Zarf pkg already exists, skipping create") + return + } + args := strings.Split(fmt.Sprintf("zarf package create %s -o %s -a %s --confirm", path, path, arch), " ") + _, _, err = e2e.UDS(args...) + require.NoError(t, err) +} + // DeleteZarfPkg deletes a Zarf package from the given path func (e2e *UDSE2ETest) DeleteZarfPkg(t *testing.T, path string) { // check if pkg already exists diff --git a/src/test/e2e/bundle_test.go b/src/test/e2e/bundle_test.go index ae225d25..8db3e99c 100644 --- a/src/test/e2e/bundle_test.go +++ b/src/test/e2e/bundle_test.go @@ -624,3 +624,22 @@ func TestInvalidBundle(t *testing.T) { stderr := createLocalError(bundleDir, e2e.Arch) require.Contains(t, stderr, "unknown field") } + +func TestArchCheck(t *testing.T) { + testArch := "arm64" + + // use arch that is different from system arch + if e2e.Arch == "arm64" { + testArch = "amd64" + } + + deployZarfInit(t) + zarfPkgPath := "src/test/packages/helm" + e2e.CreateZarfPkgWithArch(t, zarfPkgPath, false, testArch) + bundleDir := "src/test/bundles/07-helm-overrides" + bundlePath := filepath.Join(bundleDir, fmt.Sprintf("uds-bundle-helm-overrides-%s-0.0.1.tar.zst", testArch)) + createLocal(t, bundleDir, testArch) + cmd := strings.Split(fmt.Sprintf("deploy %s --confirm", bundlePath), " ") + _, stderr, _ := e2e.UDS(cmd...) + require.Contains(t, stderr, fmt.Sprintf("arch %s does not match cluster arch, [%s]", testArch, e2e.Arch)) +}