From 672e2b9d20ad3db26c07e11efd4c7836f3f491a8 Mon Sep 17 00:00:00 2001 From: Brandt Keller Date: Fri, 1 May 2026 21:12:08 -0700 Subject: [PATCH] feat(skeleton): support for values feature with skeleton packages Signed-off-by: Brandt Keller --- src/pkg/packager/layout/assemble.go | 18 +++ src/pkg/packager/layout/layout_test.go | 25 +++- src/pkg/packager/layout/package_test.go | 11 +- .../pkg-values/values.schema.json | 7 ++ .../pkg-values/values.yaml | 1 + .../testdata/zarf-skeleton-package/zarf.yaml | 4 + src/pkg/packager/load/import.go | 85 ++++++++++++- src/pkg/packager/load/import_oci_test.go | 114 ++++++++++++++++++ src/pkg/packager/load/import_test.go | 91 +++++++++++++- src/pkg/packager/load/load_test.go | 10 +- src/pkg/packager/load/main_test.go | 22 ++++ .../import/import/archives/expected.yaml | 13 ++ .../import/import/archives/import/zarf.yaml | 10 ++ .../testdata/import/import/archives/zarf.yaml | 12 ++ .../import/import/branch/child/zarf.yaml | 12 ++ .../import/import/branch/common/zarf.yaml | 10 ++ .../import/import/branch/expected.yaml | 10 ++ .../testdata/import/import/branch/zarf.yaml | 15 +++ .../import/import/chart/common/zarf.yaml | 13 ++ .../import/import/chart/expected.yaml | 15 +++ .../testdata/import/import/chart/zarf.yaml | 16 +++ .../import/import/circular/first/zarf.yaml | 8 ++ .../import/import/circular/second/zarf.yaml | 8 ++ .../import/import/circular/third/zarf.yaml | 8 ++ .../import/import/flavor/child/zarf.yaml | 10 ++ .../import/import/flavor/expected.yaml | 12 ++ .../testdata/import/import/flavor/zarf.yaml | 17 +++ .../import/import-each-other/expected.yaml | 8 ++ .../import-each-other/first-import/zarf.yaml | 12 ++ .../import-each-other/second-import/zarf.yaml | 12 ++ .../import/import/import-each-other/zarf.yaml | 13 ++ .../duplicate-consecutive/expected.yaml | 12 ++ .../duplicate-consecutive/import/zarf.yaml | 9 ++ .../values/duplicate-consecutive/zarf.yaml | 17 +++ .../duplicate-interleaved/expected.yaml | 15 +++ .../import-a/a-values.yaml | 2 + .../duplicate-interleaved/import-a/zarf.yaml | 9 ++ .../import-b/b-values.yaml | 2 + .../duplicate-interleaved/import-b/zarf.yaml | 9 ++ .../duplicate-interleaved/parent-values.yaml | 1 + .../values/duplicate-interleaved/zarf.yaml | 22 ++++ .../values/multiple-imports/expected.yaml | 13 ++ .../multiple-imports/import-a/zarf.yaml | 9 ++ .../multiple-imports/import-b/zarf.yaml | 9 ++ .../import/values/multiple-imports/zarf.yaml | 15 +++ .../values/precedence-order/expected.yaml | 11 ++ .../middle/bottom/bottom-values.yaml | 2 + .../precedence-order/middle/bottom/zarf.yaml | 9 ++ .../middle/middle-values.yaml | 2 + .../values/precedence-order/middle/zarf.yaml | 11 ++ .../values/precedence-order/top-values.yaml | 2 + .../import/values/precedence-order/zarf.yaml | 11 ++ .../values/schema-parent-empty/expected.yaml | 10 ++ .../schema-parent-empty/import/zarf.yaml | 10 ++ .../values/schema-parent-empty/zarf.yaml | 11 ++ .../values/schema-parent-wins/expected.yaml | 11 ++ .../schema-parent-wins/import/zarf.yaml | 10 ++ .../values/schema-parent-wins/zarf.yaml | 12 ++ .../import/import/variables/expected.yaml | 22 ++++ .../import/import/variables/import/zarf.yaml | 18 +++ .../import/variables/secondImport/zarf.yaml | 18 +++ .../import/import/variables/zarf.yaml | 22 ++++ 62 files changed, 935 insertions(+), 23 deletions(-) create mode 100644 src/pkg/packager/layout/testdata/zarf-skeleton-package/pkg-values/values.schema.json create mode 100644 src/pkg/packager/layout/testdata/zarf-skeleton-package/pkg-values/values.yaml create mode 100644 src/pkg/packager/load/import_oci_test.go create mode 100644 src/pkg/packager/load/main_test.go create mode 100644 src/pkg/packager/load/testdata/import/import/archives/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/archives/import/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/archives/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/branch/child/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/branch/common/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/branch/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/branch/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/chart/common/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/chart/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/chart/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/circular/first/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/circular/second/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/circular/third/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/flavor/child/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/flavor/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/flavor/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/import-each-other/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/import-each-other/first-import/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/import-each-other/second-import/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/import-each-other/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/import/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-a/a-values.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-a/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-b/b-values.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-b/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/parent-values.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/multiple-imports/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/multiple-imports/import-a/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/multiple-imports/import-b/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/multiple-imports/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/precedence-order/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/bottom/bottom-values.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/bottom/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/middle-values.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/precedence-order/top-values.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/precedence-order/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/import/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/import/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/variables/expected.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/variables/import/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/variables/secondImport/zarf.yaml create mode 100644 src/pkg/packager/load/testdata/import/import/variables/zarf.yaml diff --git a/src/pkg/packager/layout/assemble.go b/src/pkg/packager/layout/assemble.go index e7e8bd2104..905e57055e 100644 --- a/src/pkg/packager/layout/assemble.go +++ b/src/pkg/packager/layout/assemble.go @@ -242,6 +242,7 @@ type AssembleSkeletonOptions struct { // AssembleSkeleton creates a skeleton package and returns the path to the created package. func AssembleSkeleton(ctx context.Context, pkg v1alpha1.ZarfPackage, packagePath string, opts AssembleSkeletonOptions) (*PackageLayout, error) { + l := logger.From(ctx) pkg.Metadata.Architecture = v1alpha1.SkeletonArch buildPath, err := utils.MakeTempDir(config.CommonOptions.TempDirectory) @@ -249,6 +250,23 @@ func AssembleSkeleton(ctx context.Context, pkg v1alpha1.ZarfPackage, packagePath return nil, err } + // Bundle package-level values the same way AssemblePackage does: merge into a single + // values.yaml at the build root, copy the schema flat, then rewrite the spec fields so + // the published zarf.yaml points at those paths for downstream importers. + if len(pkg.Values.Files) > 0 { + l.Debug("merging values files to package", "files", pkg.Values.Files) + if err = mergeAndWriteValuesFile(ctx, pkg.Values.Files, packagePath, buildPath); err != nil { + return nil, err + } + pkg.Values.Files = []string{ValuesYAML} + } + if pkg.Values.Schema != "" { + if err = copyValuesSchema(ctx, pkg.Values.Schema, packagePath, buildPath); err != nil { + return nil, err + } + pkg.Values.Schema = ValuesSchema + } + if err = createDocumentationTar(pkg, packagePath, buildPath); err != nil { return nil, err } diff --git a/src/pkg/packager/layout/layout_test.go b/src/pkg/packager/layout/layout_test.go index 274aa48b5f..5b0ed83c2a 100644 --- a/src/pkg/packager/layout/layout_test.go +++ b/src/pkg/packager/layout/layout_test.go @@ -12,12 +12,25 @@ import ( goyaml "github.com/goccy/go-yaml" "github.com/stretchr/testify/require" "github.com/zarf-dev/zarf/src/api/v1alpha1" + "github.com/zarf-dev/zarf/src/pkg/feature" "github.com/zarf-dev/zarf/src/pkg/packager/layout" "github.com/zarf-dev/zarf/src/pkg/packager/load" "github.com/zarf-dev/zarf/src/test/testutil" _ "modernc.org/sqlite" ) +// feature.Set is write-once across the test binary, so any feature this package's tests +// rely on is enabled here once before tests run. +func TestMain(m *testing.M) { + if err := feature.Set([]feature.Feature{ + {Name: feature.Values, Enabled: true}, + {Name: feature.BundleSignature, Enabled: true}, + }); err != nil { + panic(err) + } + os.Exit(m.Run()) +} + func TestAssembleSkeleton(t *testing.T) { t.Parallel() @@ -30,19 +43,29 @@ func TestAssembleSkeleton(t *testing.T) { pkgLayout, err := layout.AssembleSkeleton(ctx, pkg, "./testdata/zarf-skeleton-package", opt) require.NoError(t, err) + // Package-level values are merged to a single values.yaml at the skeleton root and the + // schema is copied flat — same storage format AssemblePackage uses. The published + // zarf.yaml's Values fields point at those rewritten paths. + require.Equal(t, []string{layout.ValuesYAML}, pkgLayout.Pkg.Values.Files) + require.Equal(t, layout.ValuesSchema, pkgLayout.Pkg.Values.Schema) + require.FileExists(t, filepath.Join(pkgLayout.DirPath(), layout.ValuesYAML)) + require.FileExists(t, filepath.Join(pkgLayout.DirPath(), layout.ValuesSchema)) + b, err := os.ReadFile(filepath.Join(pkgLayout.DirPath(), "checksums.txt")) require.NoError(t, err) expectedChecksum := `0fea7403536c0c0e2a2d9b235d4b3716e86eefd8e78e7b14412dd5a750b77474 components/kustomizations.tar 54f657b43323e1ebecb0758835b8d01a0113b61b7bab0f4a8156f031128d00f9 components/data-injections.tar 879bfe82d20f7bdcd60f9e876043cc4343af4177a6ee8b2660c304a5b6c70be7 components/files.tar +a94b27907f8c7f0945e81e29fd97c2c8574b80dd07ad619473cdf074686fdd31 values.yaml bd82245bfc3c79abfa23dcf72c8099a2788c1b6073464f1ee0c6b64b9c8ef2f6 documentation.tar +c0d7fe697e6c07add12cd49a033e5803cec1f11bc311a820433bfa2df33ef539 values.schema.json c497f1a56559ea0a9664160b32e4b377df630454ded6a3787924130c02f341a6 components/manifests.tar fb7ebee94a4479bacddd71195030a483b0b0b96d4f73f7fcd2c2c8e0fce0c5c6 components/helm-charts.tar ` require.Equal(t, expectedChecksum, string(b)) testutil.RequireNoBackslashInPackagePaths(t, pkgLayout.Pkg) - require.Equal(t, "20c2cf8bde902c8daad1ad9fb3cd9f06741550ac34401474500a24835cb36114", testutil.ChecksumZarfYAMLContent(t, pkgLayout.Pkg), "skeleton zarf.yaml checksum drift — package would differ across build hosts") + require.Equal(t, "a2b6fbb6f722d48f3385e3a0a090f48a6b30cf7f60af615a249862cc37301364", testutil.ChecksumZarfYAMLContent(t, pkgLayout.Pkg), "skeleton zarf.yaml checksum drift — package would differ across build hosts") } func writePackageToDisk(t *testing.T, pkg v1alpha1.ZarfPackage, dir string) { diff --git a/src/pkg/packager/layout/package_test.go b/src/pkg/packager/layout/package_test.go index f447485dc3..642994ed2e 100644 --- a/src/pkg/packager/layout/package_test.go +++ b/src/pkg/packager/layout/package_test.go @@ -15,7 +15,6 @@ import ( "github.com/stretchr/testify/require" "github.com/zarf-dev/zarf/src/api/v1alpha1" - "github.com/zarf-dev/zarf/src/pkg/feature" "github.com/zarf-dev/zarf/src/pkg/utils" "github.com/zarf-dev/zarf/src/test/testutil" ) @@ -1044,15 +1043,9 @@ func TestPackageLayoutVerifyPackageSignature(t *testing.T) { } // TestSignPackageBundleSignatureEnabled tests signing behavior when the BundleSignature -// feature flag is enabled. This test uses feature.Set() which is write-once, so it must -// be the last signing-related test to run. It is intentionally not parallel. +// feature flag is enabled. The feature is enabled in TestMain (layout_test.go) for the +// whole package since feature.Set is write-once. func TestSignPackageBundleSignatureEnabled(t *testing.T) { - // Enable the BundleSignature feature flag via feature.Set() - err := feature.Set([]feature.Feature{ - {Name: feature.BundleSignature, Enabled: true}, - }) - require.NoError(t, err) - ctx := testutil.TestContext(t) t.Run("signing produces both bundle and legacy formats", func(t *testing.T) { diff --git a/src/pkg/packager/layout/testdata/zarf-skeleton-package/pkg-values/values.schema.json b/src/pkg/packager/layout/testdata/zarf-skeleton-package/pkg-values/values.schema.json new file mode 100644 index 0000000000..98698fbdc3 --- /dev/null +++ b/src/pkg/packager/layout/testdata/zarf-skeleton-package/pkg-values/values.schema.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "example": { "type": "string" } + } +} diff --git a/src/pkg/packager/layout/testdata/zarf-skeleton-package/pkg-values/values.yaml b/src/pkg/packager/layout/testdata/zarf-skeleton-package/pkg-values/values.yaml new file mode 100644 index 0000000000..a4e24d8b11 --- /dev/null +++ b/src/pkg/packager/layout/testdata/zarf-skeleton-package/pkg-values/values.yaml @@ -0,0 +1 @@ +example: value diff --git a/src/pkg/packager/layout/testdata/zarf-skeleton-package/zarf.yaml b/src/pkg/packager/layout/testdata/zarf-skeleton-package/zarf.yaml index eb87a02d13..d88a1ac499 100644 --- a/src/pkg/packager/layout/testdata/zarf-skeleton-package/zarf.yaml +++ b/src/pkg/packager/layout/testdata/zarf-skeleton-package/zarf.yaml @@ -4,6 +4,10 @@ metadata: version: v0.0.1 documentation: my-doc: doc.md +values: + files: + - pkg-values/values.yaml + schema: pkg-values/values.schema.json components: - name: helm-charts required: true diff --git a/src/pkg/packager/load/import.go b/src/pkg/packager/load/import.go index dd31a1631c..1fbd1928e3 100644 --- a/src/pkg/packager/load/import.go +++ b/src/pkg/packager/load/import.go @@ -61,9 +61,13 @@ func resolveImports(ctx context.Context, pkg v1alpha1.ZarfPackage, packagePath, "importStack", len(importStack), ) + var valuesFiles []string variables := pkg.Variables constants := pkg.Constants components := []v1alpha1.ZarfComponent{} + // pkgValuesByURL memoizes per-skeleton package-scoped values dirs so multiple + // components importing the same OCI URL only materialize the top-level layers once. + pkgValuesByURL := map[string]string{} for _, component := range pkg.Components { if !compatibleComponent(component, arch, flavor) { @@ -81,6 +85,9 @@ func resolveImports(ctx context.Context, pkg v1alpha1.ZarfPackage, packagePath, } var importedPkg v1alpha1.ZarfPackage + // Set when the URL branch materializes the imported skeleton's package-scoped + // values layer; used as the rebase anchor for Values.Files. + var pkgValuesPath string if component.Import.Path != "" { importPath := filepath.Join(pkgPath.BaseDir, component.Import.Path) for _, sp := range importStack { @@ -123,7 +130,7 @@ func resolveImports(ctx context.Context, pkg v1alpha1.ZarfPackage, packagePath, if err != nil { return v1alpha1.ZarfPackage{}, err } - _, err = remote.ResolveRoot(ctx) + rootDesc, err := remote.ResolveRoot(ctx) if err != nil { if strings.Contains(err.Error(), "no matching manifest was found in the manifest list") { return v1alpha1.ZarfPackage{}, fmt.Errorf("package at %s exists but has not been published as a skeleton: %w", component.Import.URL, err) @@ -140,6 +147,62 @@ func resolveImports(ctx context.Context, pkg v1alpha1.ZarfPackage, packagePath, return v1alpha1.ZarfPackage{}, fmt.Errorf("package %s has unmet requirements: %w If you cannot upgrade Zarf you may skip this check with --skip-version-check. Unexpected behavior or errors may occur", component.Import.URL, err) } } + + // Materialize the published package-scoped values layer (fixed name per + // AssembleSkeleton's contract) into a per-skeleton cache dir keyed by root + // manifest digest. Memoized per URL so multiple components importing the + // same skeleton only pull once. Schema propagation is intentionally left + // for a follow-up — see TestResolveImports/schema-parent-{empty,wins}. + if len(importedPkg.Values.Files) > 0 { + if cached, ok := pkgValuesByURL[component.Import.URL]; ok { + pkgValuesPath = cached + } else { + cache := filepath.Join(cachePath, "oci") + if err := helpers.CreateDirectory(cache, helpers.ReadWriteExecuteUser); err != nil { + return v1alpha1.ZarfPackage{}, err + } + manifest, err := remote.FetchRoot(ctx) + if err != nil { + return v1alpha1.ZarfPackage{}, err + } + pkgDir := filepath.Join(cache, "pkgs", rootDesc.Digest.Encoded()) + if err := helpers.CreateDirectory(pkgDir, helpers.ReadWriteExecuteUser); err != nil { + return v1alpha1.ZarfPackage{}, err + } + store, err := ocistore.New(cache) + if err != nil { + return v1alpha1.ZarfPackage{}, err + } + desc := manifest.Locate(layout.ValuesYAML) + if oci.IsEmptyDescriptor(desc) { + return v1alpha1.ZarfPackage{}, fmt.Errorf("skeleton %s declares values but %q layer was not published", component.Import.URL, layout.ValuesYAML) + } + exists, err := store.Exists(ctx, desc) + if err != nil { + return v1alpha1.ZarfPackage{}, err + } + if !exists { + if err := remote.CopyToTarget(ctx, []ocispec.Descriptor{desc}, store, remote.GetDefaultCopyOpts()); err != nil { + return v1alpha1.ZarfPackage{}, err + } + } + src := filepath.Join(cache, "blobs", "sha256", desc.Digest.Encoded()) + dst := filepath.Join(pkgDir, layout.ValuesYAML) + if err := helpers.CreatePathAndCopy(src, dst); err != nil { + return v1alpha1.ZarfPackage{}, fmt.Errorf("unable to materialize %s for skeleton %s: %w", layout.ValuesYAML, component.Import.URL, err) + } + abs, err := filepath.Abs(pkgPath.BaseDir) + if err != nil { + return v1alpha1.ZarfPackage{}, err + } + rel, err := filepath.Rel(abs, pkgDir) + if err != nil { + return v1alpha1.ZarfPackage{}, err + } + pkgValuesPath = rel + pkgValuesByURL[component.Import.URL] = pkgValuesPath + } + } } name := getComponentToImportName(component) @@ -182,8 +245,28 @@ func resolveImports(ctx context.Context, pkg v1alpha1.ZarfPackage, packagePath, components = append(components, composed) variables = append(variables, importedPkg.Variables...) constants = append(constants, importedPkg.Constants...) + + // pkg.Values.Files is package-scoped. URL imports rebase against the + // per-skeleton cache dir set up earlier in the URL branch; path imports + // continue to anchor at the per-component importPath as before. + valuesAnchorPath := importPath + if pkgValuesPath != "" { + valuesAnchorPath = pkgValuesPath + } + for _, v := range importedPkg.Values.Files { + valuesFiles = append(valuesFiles, makePathRelativeTo(v, valuesAnchorPath)) + } } + valuesFiles = append(valuesFiles, pkg.Values.Files...) + valuesFilesMap := map[string]bool{} + pkg.Values.Files = nil + for _, v := range valuesFiles { + if _, present := valuesFilesMap[v]; !present { + pkg.Values.Files = append(pkg.Values.Files, v) + valuesFilesMap[v] = true + } + } pkg.Components = components varMap := map[string]bool{} diff --git a/src/pkg/packager/load/import_oci_test.go b/src/pkg/packager/load/import_oci_test.go new file mode 100644 index 0000000000..7369dc099c --- /dev/null +++ b/src/pkg/packager/load/import_oci_test.go @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2021-Present The Zarf Authors + +package load_test + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/defenseunicorns/pkg/helpers/v2" + "github.com/stretchr/testify/require" + "oras.land/oras-go/v2/registry" + + "github.com/zarf-dev/zarf/src/pkg/packager" + "github.com/zarf-dev/zarf/src/pkg/packager/load" + "github.com/zarf-dev/zarf/src/test/testutil" + "github.com/zarf-dev/zarf/src/types" +) + +// TestResolveImportsOCISkeletonValues exercises the OCI skeleton import path: a parent +// package importing a values-bearing skeleton via oci:// must materialize the skeleton's +// merged values.yaml on disk and rewrite Values.Files to a path the consumer can read. +// The publisher-side merge happens in AssembleSkeleton; this test verifies the importer +// side picks the file up. Schema propagation is intentionally out of scope here — see +// the existing TestResolveImports/schema-parent-* fixtures and follow-up work. +func TestResolveImportsOCISkeletonValues(t *testing.T) { + ctx := testutil.TestContext(t) + + tmp := t.TempDir() + cachePath := filepath.Join(tmp, "cache") + require.NoError(t, os.MkdirAll(cachePath, 0o755)) + + // Skeleton: declares package-level values + schema. + skeletonDir := filepath.Join(tmp, "skeleton") + require.NoError(t, os.MkdirAll(filepath.Join(skeletonDir, "vals"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(skeletonDir, "vals", "values.yaml"), + []byte("greeting: hello\n"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(skeletonDir, "vals", "values.schema.json"), + []byte(`{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"greeting":{"type":"string"}}}`+"\n"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(skeletonDir, "zarf.yaml"), []byte( + `kind: ZarfPackageConfig +metadata: + name: skeleton-with-values + version: 0.0.1 +values: + files: + - vals/values.yaml + schema: vals/values.schema.json +components: + - name: noop + required: true +`), 0o644)) + + // Spin up a real in-memory OCI registry on a free port. + port, err := helpers.GetAvailablePort() + require.NoError(t, err) + registryURL := testutil.SetupInMemoryRegistry(ctx, t, port) + registryRef := registry.Reference{ + Registry: registryURL, + Repository: "test", + } + + publishedRef, err := packager.PublishSkeleton(ctx, skeletonDir, registryRef, packager.PublishSkeletonOptions{ + CachePath: cachePath, + RemoteOptions: types.RemoteOptions{PlainHTTP: true}, + }) + require.NoError(t, err) + + // Parent: imports the skeleton via oci://. Defines its own additional values file so we + // can also confirm parent + imported values end up in the resolved Values.Files list. + parentDir := filepath.Join(tmp, "parent") + require.NoError(t, os.MkdirAll(parentDir, 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(parentDir, "parent-values.yaml"), + []byte("override: parent\n"), 0o644)) + parentYAML := fmt.Sprintf(`kind: ZarfPackageConfig +metadata: + name: parent + version: 0.0.1 +values: + files: + - parent-values.yaml +components: + - name: noop + required: true + import: + url: oci://%s +`, publishedRef.String()) + require.NoError(t, os.WriteFile(filepath.Join(parentDir, "zarf.yaml"), []byte(parentYAML), 0o644)) + + resolved, err := load.PackageDefinition(ctx, parentDir, load.DefinitionOptions{ + CachePath: cachePath, + RemoteOptions: types.RemoteOptions{PlainHTTP: true}, + }) + require.NoError(t, err) + + // The imported skeleton's merged values must come first (deepest-first), then the parent's. + require.Len(t, resolved.Values.Files, 2, + "expected one values file from imported skeleton plus one from parent, got %v", resolved.Values.Files) + require.Equal(t, "parent-values.yaml", resolved.Values.Files[1]) + + // Imported values path must resolve to a real file on disk relative to the parent's BaseDir. + importedRel := resolved.Values.Files[0] + importedAbs := filepath.Join(parentDir, importedRel) + require.FileExists(t, importedAbs, + "expected imported skeleton values to materialize on disk at %s", importedAbs) + + // Schema propagation across imports is left for future work (path imports also + // don't propagate today — see TestResolveImports/schema-parent-empty). Parent + // declares none, so resolved schema stays empty. + require.Empty(t, resolved.Values.Schema, + "schema propagation is not part of this fix; parent declares none, so resolved schema must stay empty") +} diff --git a/src/pkg/packager/load/import_test.go b/src/pkg/packager/load/import_test.go index 795a0faa82..9abf51f0f6 100644 --- a/src/pkg/packager/load/import_test.go +++ b/src/pkg/packager/load/import_test.go @@ -14,6 +14,7 @@ import ( "github.com/zarf-dev/zarf/src/api/v1alpha1" "github.com/zarf-dev/zarf/src/internal/pkgcfg" "github.com/zarf-dev/zarf/src/pkg/packager/layout" + "github.com/zarf-dev/zarf/src/pkg/value" "github.com/zarf-dev/zarf/src/test/testutil" "github.com/zarf-dev/zarf/src/types" ) @@ -52,6 +53,36 @@ func TestResolveImports(t *testing.T) { path: "./testdata/import/variables", expectedChecksum: "41e3bdf823769eb2c13079191179ee723a6b8550c5492a8668233de8b77e03da", }, + { + name: "values files from nested imports preserve deepest-first precedence order", + path: "./testdata/import/values/precedence-order", + expectedChecksum: "1269606562ec5f7065169f601f0c3d7dff4707ec613216050f513b4ea0161849", + }, + { + name: "values files from multiple sibling imports preserve left-to-right order", + path: "./testdata/import/values/multiple-imports", + expectedChecksum: "06b9e2cbc17034b371efd57f75bb299e4849b8644f4fdde257f778ff2c48fb01", + }, + { + name: "duplicate values file paths from consecutive imports are deduplicated", + path: "./testdata/import/values/duplicate-consecutive", + expectedChecksum: "9698b8c12900a862f370d12bf240c721a62b5508fc26a34af33cd787261eaca3", + }, + { + name: "duplicate values file paths from non-consecutive imports are deduplicated", + path: "./testdata/import/values/duplicate-interleaved", + expectedChecksum: "23c92f2941e30e5717546a0f4d3cd76ced28787346d4681936d0acb1df204255", + }, + { + name: "an empty parent schema is kept even when an imported package has one", + path: "./testdata/import/values/schema-parent-empty", + expectedChecksum: "63135e84455ebf25324cbe847d2c778da2adecee477d7c0172744b9825e8615f", + }, + { + name: "a parent schema takes precedence over an imported package's schema", + path: "./testdata/import/values/schema-parent-wins", + expectedChecksum: "e43e13f0f064be03780d69f2772caed374e9f4c30ddfd8c0f09dcb0461a6e53d", + }, { name: "two separate chains of imports importing a common file", path: "./testdata/import/branch", @@ -64,9 +95,8 @@ func TestResolveImports(t *testing.T) { expectedChecksum: "9c60125954b1b38a5947401411b87cde3d586e5ff8eef03bcc37dae1e24ab08e", }, { - name: "chart version and url properties are not overridden", - path: "./testdata/import/chart", - + name: "chart version and url properties are not overridden", + path: "./testdata/import/chart", expectedChecksum: "cc62674a6faa1c9685aac0c8266dacec3b91e0a9466c8d1ce3664e019348b43a", }, { @@ -150,6 +180,61 @@ func TestMakePathRelativeTo(t *testing.T) { } } +func TestResolveImportsValueMerge(t *testing.T) { + t.Parallel() + ctx := testutil.TestContext(t) + + testCases := []struct { + name string + path string + expected value.Values + }{ + { + name: "nested imports apply deepest-first so parent overrides inner values", + path: "./testdata/import/values/precedence-order", + expected: value.Values{ + "shared": "top", + "top-only": "present", + "middle-only": "present", + "bottom-only": "present", + }, + }, + { + name: "non-consecutive duplicate imports are deduplicated so the later sibling's value wins", + path: "./testdata/import/values/duplicate-interleaved", + expected: value.Values{ + "origin": "b", + "a-only": "present", + "b-only": "present", + "parent-only": "present", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + b, err := os.ReadFile(filepath.Join(tc.path, layout.ZarfYAML)) + require.NoError(t, err) + pkg, err := pkgcfg.Parse(ctx, b) + require.NoError(t, err) + + resolved, err := resolveImports(ctx, pkg, tc.path, "", "", []string{}, "", false, types.RemoteOptions{}) + require.NoError(t, err) + + absPaths := make([]string, len(resolved.Values.Files)) + for i, f := range resolved.Values.Files { + absPaths[i] = filepath.Join(tc.path, f) + } + + merged, err := value.ParseFiles(ctx, absPaths, value.ParseFilesOptions{}) + require.NoError(t, err) + require.Equal(t, tc.expected, merged) + }) + } +} + func TestValidateComponentCompose(t *testing.T) { t.Parallel() diff --git a/src/pkg/packager/load/load_test.go b/src/pkg/packager/load/load_test.go index e6dfa0af85..d7cfee3871 100644 --- a/src/pkg/packager/load/load_test.go +++ b/src/pkg/packager/load/load_test.go @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/require" "github.com/zarf-dev/zarf/src/api/v1alpha1" - "github.com/zarf-dev/zarf/src/pkg/feature" "github.com/zarf-dev/zarf/src/test/testutil" ) @@ -116,14 +115,7 @@ func TestPackageUsesFlavor(t *testing.T) { func TestPackageDefinitionWithValuesSchema(t *testing.T) { t.Parallel() - // Enable the values feature for these tests - err := feature.Set([]feature.Feature{ - { - Name: feature.Values, - Enabled: true, - }, - }) - require.NoError(t, err) + // Values feature is enabled in TestMain (main_test.go) since feature.Set is write-once. tests := []struct { name string diff --git a/src/pkg/packager/load/main_test.go b/src/pkg/packager/load/main_test.go new file mode 100644 index 0000000000..2b590c5fd4 --- /dev/null +++ b/src/pkg/packager/load/main_test.go @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2021-Present The Zarf Authors + +package load + +import ( + "os" + "testing" + + "github.com/zarf-dev/zarf/src/pkg/feature" +) + +// feature.Set is write-once across the test binary, so any feature this package's tests +// rely on is enabled here once before tests run. +func TestMain(m *testing.M) { + if err := feature.Set([]feature.Feature{ + {Name: feature.Values, Enabled: true}, + }); err != nil { + panic(err) + } + os.Exit(m.Run()) +} diff --git a/src/pkg/packager/load/testdata/import/import/archives/expected.yaml b/src/pkg/packager/load/testdata/import/import/archives/expected.yaml new file mode 100644 index 0000000000..5ca4947ba4 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/archives/expected.yaml @@ -0,0 +1,13 @@ +kind: ZarfPackageConfig +metadata: + name: example-archives + +components: + - name: component + imageArchives: + - path: image.tar + images: + - my-image:2 + - path: image.tar + images: + - my-image:1 diff --git a/src/pkg/packager/load/testdata/import/import/archives/import/zarf.yaml b/src/pkg/packager/load/testdata/import/import/archives/import/zarf.yaml new file mode 100644 index 0000000000..c47061da3b --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/archives/import/zarf.yaml @@ -0,0 +1,10 @@ +kind: ZarfPackageConfig +metadata: + name: example-archives + +components: + - name: component + imageArchives: + - path: ../image.tar + images: + - my-image:2 diff --git a/src/pkg/packager/load/testdata/import/import/archives/zarf.yaml b/src/pkg/packager/load/testdata/import/import/archives/zarf.yaml new file mode 100644 index 0000000000..3695c8e99e --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/archives/zarf.yaml @@ -0,0 +1,12 @@ +kind: ZarfPackageConfig +metadata: + name: example-archives + +components: + - name: component + import: + path: import + imageArchives: + - path: image.tar + images: + - my-image:1 diff --git a/src/pkg/packager/load/testdata/import/import/branch/child/zarf.yaml b/src/pkg/packager/load/testdata/import/import/branch/child/zarf.yaml new file mode 100644 index 0000000000..99d53d5a9f --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/branch/child/zarf.yaml @@ -0,0 +1,12 @@ +kind: ZarfPackageConfig +metadata: + name: example-child + +components: + - name: common + import: + path: ../common + + - name: parent-child-common + import: + path: ../common diff --git a/src/pkg/packager/load/testdata/import/import/branch/common/zarf.yaml b/src/pkg/packager/load/testdata/import/import/branch/common/zarf.yaml new file mode 100644 index 0000000000..1dfdc71f09 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/branch/common/zarf.yaml @@ -0,0 +1,10 @@ +kind: ZarfPackageConfig +metadata: + name: example-shared + +components: + - name: common + description: This gets imported by the parent and child directly + + - name: parent-child-common + description: This gets imported in a chain parent->child->common diff --git a/src/pkg/packager/load/testdata/import/import/branch/expected.yaml b/src/pkg/packager/load/testdata/import/import/branch/expected.yaml new file mode 100644 index 0000000000..2bf4d4e03c --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/branch/expected.yaml @@ -0,0 +1,10 @@ +kind: ZarfPackageConfig +metadata: + name: example-package +components: +- name: common + description: This gets imported by the parent and child directly + required: true +- name: parent-importing-child + description: This gets imported in a chain parent->child->common + required: true diff --git a/src/pkg/packager/load/testdata/import/import/branch/zarf.yaml b/src/pkg/packager/load/testdata/import/import/branch/zarf.yaml new file mode 100644 index 0000000000..3dcf3b70c1 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/branch/zarf.yaml @@ -0,0 +1,15 @@ +kind: ZarfPackageConfig +metadata: + name: example-package + +components: + - name: common + required: true + import: + path: common + + - name: parent-importing-child + required: true + import: + name: parent-child-common + path: child diff --git a/src/pkg/packager/load/testdata/import/import/chart/common/zarf.yaml b/src/pkg/packager/load/testdata/import/import/chart/common/zarf.yaml new file mode 100644 index 0000000000..13545036b8 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/chart/common/zarf.yaml @@ -0,0 +1,13 @@ +kind: ZarfPackageConfig +metadata: + name: example-shared + +components: + - name: common + charts: + - name: chart + url: oci://test/placeholder + version: 1.2.3 + values: + - sourcePath: .baseValue + targetPath: .config.base diff --git a/src/pkg/packager/load/testdata/import/import/chart/expected.yaml b/src/pkg/packager/load/testdata/import/import/chart/expected.yaml new file mode 100644 index 0000000000..2ee2a99870 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/chart/expected.yaml @@ -0,0 +1,15 @@ +kind: ZarfPackageConfig +metadata: + name: example-package +components: +- name: common + required: true + charts: + - name: chart + url: oci://test/different-value + version: 2.3.4 + values: + - sourcePath: .baseValue + targetPath: .config.base + - sourcePath: .overrideValue + targetPath: .config.override diff --git a/src/pkg/packager/load/testdata/import/import/chart/zarf.yaml b/src/pkg/packager/load/testdata/import/import/chart/zarf.yaml new file mode 100644 index 0000000000..ae58b3113d --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/chart/zarf.yaml @@ -0,0 +1,16 @@ +kind: ZarfPackageConfig +metadata: + name: example-package + +components: + - name: common + required: true + import: + path: common + charts: + - name: chart + url: oci://test/different-value + version: 2.3.4 + values: + - sourcePath: .overrideValue + targetPath: .config.override diff --git a/src/pkg/packager/load/testdata/import/import/circular/first/zarf.yaml b/src/pkg/packager/load/testdata/import/import/circular/first/zarf.yaml new file mode 100644 index 0000000000..1e2e71b678 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/circular/first/zarf.yaml @@ -0,0 +1,8 @@ +kind: ZarfPackageConfig +metadata: + name: first +components: + - name: component + required: true + import: + path: ../second diff --git a/src/pkg/packager/load/testdata/import/import/circular/second/zarf.yaml b/src/pkg/packager/load/testdata/import/import/circular/second/zarf.yaml new file mode 100644 index 0000000000..9fbc0e3a3f --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/circular/second/zarf.yaml @@ -0,0 +1,8 @@ +kind: ZarfPackageConfig +metadata: + name: second +components: + - name: component + required: true + import: + path: ../third diff --git a/src/pkg/packager/load/testdata/import/import/circular/third/zarf.yaml b/src/pkg/packager/load/testdata/import/import/circular/third/zarf.yaml new file mode 100644 index 0000000000..080ce55337 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/circular/third/zarf.yaml @@ -0,0 +1,8 @@ +kind: ZarfPackageConfig +metadata: + name: third +components: + - name: component + required: true + import: + path: ../second diff --git a/src/pkg/packager/load/testdata/import/import/flavor/child/zarf.yaml b/src/pkg/packager/load/testdata/import/import/flavor/child/zarf.yaml new file mode 100644 index 0000000000..f561649834 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/flavor/child/zarf.yaml @@ -0,0 +1,10 @@ +kind: ZarfPackageConfig +metadata: + name: example-package-flavors-child + +components: + - name: has-no-flavor + + - name: child-has-flavor + only: + flavor: pistachio diff --git a/src/pkg/packager/load/testdata/import/import/flavor/expected.yaml b/src/pkg/packager/load/testdata/import/import/flavor/expected.yaml new file mode 100644 index 0000000000..ec5b75b9ff --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/flavor/expected.yaml @@ -0,0 +1,12 @@ +kind: ZarfPackageConfig +metadata: + name: example-package-flavors +components: + - name: has-flavor + description: this already has a flavor so it shouldn't get overwritten + only: + flavor: pistachio + - name: child-has-flavor + description: this doesn't have a flavor so it should get it's child's flavor + only: + flavor: pistachio diff --git a/src/pkg/packager/load/testdata/import/import/flavor/zarf.yaml b/src/pkg/packager/load/testdata/import/import/flavor/zarf.yaml new file mode 100644 index 0000000000..6a12a81dab --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/flavor/zarf.yaml @@ -0,0 +1,17 @@ +kind: ZarfPackageConfig +metadata: + name: example-package-flavors + +components: + - name: has-flavor + description: this already has a flavor so it shouldn't get overwritten + import: + path: child + name: has-no-flavor + only: + flavor: pistachio + + - name: child-has-flavor + description: this doesn't have a flavor so it should get it's child's flavor + import: + path: child diff --git a/src/pkg/packager/load/testdata/import/import/import-each-other/expected.yaml b/src/pkg/packager/load/testdata/import/import/import-each-other/expected.yaml new file mode 100644 index 0000000000..ee6245f5a8 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/import-each-other/expected.yaml @@ -0,0 +1,8 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +components: +- name: first-is-parent + description: this component gets imported by second-package +- name: second-is-parent + description: this component gets imported by first-package diff --git a/src/pkg/packager/load/testdata/import/import/import-each-other/first-import/zarf.yaml b/src/pkg/packager/load/testdata/import/import/import-each-other/first-import/zarf.yaml new file mode 100644 index 0000000000..b2a9efbbd1 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/import-each-other/first-import/zarf.yaml @@ -0,0 +1,12 @@ +kind: ZarfPackageConfig +metadata: + name: first-package + +components: + - name: first-is-parent + description: "this component gets imported by second-package" + + - name: second-is-parent + description: "this component imports second-package" + import: + path: ../second-import diff --git a/src/pkg/packager/load/testdata/import/import/import-each-other/second-import/zarf.yaml b/src/pkg/packager/load/testdata/import/import/import-each-other/second-import/zarf.yaml new file mode 100644 index 0000000000..70893e6081 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/import-each-other/second-import/zarf.yaml @@ -0,0 +1,12 @@ +kind: ZarfPackageConfig +metadata: + name: second-package + +components: + - name: first-is-parent + description: "this component imports first-package" + import: + path: ../first-import + + - name: second-is-parent + description: "this component gets imported by first-package" diff --git a/src/pkg/packager/load/testdata/import/import/import-each-other/zarf.yaml b/src/pkg/packager/load/testdata/import/import/import-each-other/zarf.yaml new file mode 100644 index 0000000000..70a0645d84 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/import-each-other/zarf.yaml @@ -0,0 +1,13 @@ +kind: ZarfPackageConfig + +metadata: + name: parent-package + +components: + - name: first-is-parent + import: + path: first-import + + - name: second-is-parent + import: + path: second-import diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/expected.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/expected.yaml new file mode 100644 index 0000000000..0556235222 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/expected.yaml @@ -0,0 +1,12 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - import/child-values.yaml + - parent-values.yaml +components: + - name: first + required: true + - name: second + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/import/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/import/zarf.yaml new file mode 100644 index 0000000000..909158baa4 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/import/zarf.yaml @@ -0,0 +1,9 @@ +kind: ZarfPackageConfig +metadata: + name: child-package +values: + files: + - child-values.yaml +components: + - name: shared + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/zarf.yaml new file mode 100644 index 0000000000..5e75489280 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-consecutive/zarf.yaml @@ -0,0 +1,17 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - parent-values.yaml +components: + - name: first + required: true + import: + path: import + name: shared + - name: second + required: true + import: + path: import + name: shared diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/expected.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/expected.yaml new file mode 100644 index 0000000000..cf54190d5d --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/expected.yaml @@ -0,0 +1,15 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - import-a/a-values.yaml + - import-b/b-values.yaml + - parent-values.yaml +components: + - name: a-first + required: true + - name: b-only + required: true + - name: a-again + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-a/a-values.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-a/a-values.yaml new file mode 100644 index 0000000000..54c40b4f24 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-a/a-values.yaml @@ -0,0 +1,2 @@ +origin: "a" +a-only: "present" diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-a/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-a/zarf.yaml new file mode 100644 index 0000000000..1933aa6a0d --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-a/zarf.yaml @@ -0,0 +1,9 @@ +kind: ZarfPackageConfig +metadata: + name: import-a-package +values: + files: + - a-values.yaml +components: + - name: shared + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-b/b-values.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-b/b-values.yaml new file mode 100644 index 0000000000..7e31ea06d3 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-b/b-values.yaml @@ -0,0 +1,2 @@ +origin: "b" +b-only: "present" diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-b/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-b/zarf.yaml new file mode 100644 index 0000000000..73604ee732 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/import-b/zarf.yaml @@ -0,0 +1,9 @@ +kind: ZarfPackageConfig +metadata: + name: import-b-package +values: + files: + - b-values.yaml +components: + - name: shared + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/parent-values.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/parent-values.yaml new file mode 100644 index 0000000000..f55c23fb8e --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/parent-values.yaml @@ -0,0 +1 @@ +parent-only: "present" diff --git a/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/zarf.yaml new file mode 100644 index 0000000000..a68ffe51b8 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/duplicate-interleaved/zarf.yaml @@ -0,0 +1,22 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - parent-values.yaml +components: + - name: a-first + required: true + import: + path: import-a + name: shared + - name: b-only + required: true + import: + path: import-b + name: shared + - name: a-again + required: true + import: + path: import-a + name: shared diff --git a/src/pkg/packager/load/testdata/import/import/values/multiple-imports/expected.yaml b/src/pkg/packager/load/testdata/import/import/values/multiple-imports/expected.yaml new file mode 100644 index 0000000000..767f93d693 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/multiple-imports/expected.yaml @@ -0,0 +1,13 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - import-a/a-values.yaml + - import-b/b-values.yaml + - parent-values.yaml +components: + - name: component-a + required: true + - name: component-b + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/multiple-imports/import-a/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/multiple-imports/import-a/zarf.yaml new file mode 100644 index 0000000000..e5c4f19bac --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/multiple-imports/import-a/zarf.yaml @@ -0,0 +1,9 @@ +kind: ZarfPackageConfig +metadata: + name: import-a-package +values: + files: + - a-values.yaml +components: + - name: component-a + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/multiple-imports/import-b/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/multiple-imports/import-b/zarf.yaml new file mode 100644 index 0000000000..3e4c298806 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/multiple-imports/import-b/zarf.yaml @@ -0,0 +1,9 @@ +kind: ZarfPackageConfig +metadata: + name: import-b-package +values: + files: + - b-values.yaml +components: + - name: component-b + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/multiple-imports/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/multiple-imports/zarf.yaml new file mode 100644 index 0000000000..aad22bda99 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/multiple-imports/zarf.yaml @@ -0,0 +1,15 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - parent-values.yaml +components: + - name: component-a + required: true + import: + path: import-a + - name: component-b + required: true + import: + path: import-b diff --git a/src/pkg/packager/load/testdata/import/import/values/precedence-order/expected.yaml b/src/pkg/packager/load/testdata/import/import/values/precedence-order/expected.yaml new file mode 100644 index 0000000000..e10fb49741 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/precedence-order/expected.yaml @@ -0,0 +1,11 @@ +kind: ZarfPackageConfig +metadata: + name: top-package +values: + files: + - middle/bottom/bottom-values.yaml + - middle/middle-values.yaml + - top-values.yaml +components: + - name: nested-component + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/bottom/bottom-values.yaml b/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/bottom/bottom-values.yaml new file mode 100644 index 0000000000..81ac5149b8 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/bottom/bottom-values.yaml @@ -0,0 +1,2 @@ +shared: "bottom" +bottom-only: "present" diff --git a/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/bottom/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/bottom/zarf.yaml new file mode 100644 index 0000000000..562e73724a --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/bottom/zarf.yaml @@ -0,0 +1,9 @@ +kind: ZarfPackageConfig +metadata: + name: bottom-package +values: + files: + - bottom-values.yaml +components: + - name: nested-component + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/middle-values.yaml b/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/middle-values.yaml new file mode 100644 index 0000000000..2ba87bc180 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/middle-values.yaml @@ -0,0 +1,2 @@ +shared: "middle" +middle-only: "present" diff --git a/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/zarf.yaml new file mode 100644 index 0000000000..ed516d633c --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/precedence-order/middle/zarf.yaml @@ -0,0 +1,11 @@ +kind: ZarfPackageConfig +metadata: + name: middle-package +values: + files: + - middle-values.yaml +components: + - name: nested-component + required: true + import: + path: bottom diff --git a/src/pkg/packager/load/testdata/import/import/values/precedence-order/top-values.yaml b/src/pkg/packager/load/testdata/import/import/values/precedence-order/top-values.yaml new file mode 100644 index 0000000000..2867eed880 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/precedence-order/top-values.yaml @@ -0,0 +1,2 @@ +shared: "top" +top-only: "present" diff --git a/src/pkg/packager/load/testdata/import/import/values/precedence-order/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/precedence-order/zarf.yaml new file mode 100644 index 0000000000..31afcc2503 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/precedence-order/zarf.yaml @@ -0,0 +1,11 @@ +kind: ZarfPackageConfig +metadata: + name: top-package +values: + files: + - top-values.yaml +components: + - name: nested-component + required: true + import: + path: middle diff --git a/src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/expected.yaml b/src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/expected.yaml new file mode 100644 index 0000000000..634b701c80 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/expected.yaml @@ -0,0 +1,10 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - import/child-values.yaml + - parent-values.yaml +components: + - name: imported-component + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/import/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/import/zarf.yaml new file mode 100644 index 0000000000..0f39d91ba4 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/import/zarf.yaml @@ -0,0 +1,10 @@ +kind: ZarfPackageConfig +metadata: + name: child-package +values: + files: + - child-values.yaml + schema: "child-values.schema.json" +components: + - name: imported-component + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/zarf.yaml new file mode 100644 index 0000000000..eb4f650e92 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/schema-parent-empty/zarf.yaml @@ -0,0 +1,11 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - parent-values.yaml +components: + - name: imported-component + required: true + import: + path: import diff --git a/src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/expected.yaml b/src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/expected.yaml new file mode 100644 index 0000000000..e716a9df72 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/expected.yaml @@ -0,0 +1,11 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - import/child-values.yaml + - parent-values.yaml + schema: "parent-values.schema.json" +components: + - name: imported-component + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/import/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/import/zarf.yaml new file mode 100644 index 0000000000..0f39d91ba4 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/import/zarf.yaml @@ -0,0 +1,10 @@ +kind: ZarfPackageConfig +metadata: + name: child-package +values: + files: + - child-values.yaml + schema: "child-values.schema.json" +components: + - name: imported-component + required: true diff --git a/src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/zarf.yaml b/src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/zarf.yaml new file mode 100644 index 0000000000..cc7453e345 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/values/schema-parent-wins/zarf.yaml @@ -0,0 +1,12 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +values: + files: + - parent-values.yaml + schema: "parent-values.schema.json" +components: + - name: imported-component + required: true + import: + path: import diff --git a/src/pkg/packager/load/testdata/import/import/variables/expected.yaml b/src/pkg/packager/load/testdata/import/import/variables/expected.yaml new file mode 100644 index 0000000000..d169e9e6b8 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/variables/expected.yaml @@ -0,0 +1,22 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +constants: +- name: PARENT_CONSTANT + value: value from parent +- name: CHILD_CONSTANT + value: value from child +variables: + - name: PARENT_VAR + default: "default from parent" + - name: CHILD_VAR + default: "default from child" + - name: SECONDARY_CHILD_VAR + default: "default from child in component imported later" +components: + - name: first-imported-component + required: true + - name: same-package-imported-again + required: true + - name: component-from-different-package + required: true diff --git a/src/pkg/packager/load/testdata/import/import/variables/import/zarf.yaml b/src/pkg/packager/load/testdata/import/import/variables/import/zarf.yaml new file mode 100644 index 0000000000..4b7867a283 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/variables/import/zarf.yaml @@ -0,0 +1,18 @@ +kind: ZarfPackageConfig +metadata: + name: child-package +constants: + - name: PARENT_CONSTANT + value: "value from child" + - name: CHILD_CONSTANT + value: "value from child" +variables: + - name: PARENT_VAR + default: "default from child" + - name: CHILD_VAR + default: "default from child" +components: + - name: first-imported-component + required: true + - name: same-package-imported-again + required: true diff --git a/src/pkg/packager/load/testdata/import/import/variables/secondImport/zarf.yaml b/src/pkg/packager/load/testdata/import/import/variables/secondImport/zarf.yaml new file mode 100644 index 0000000000..7ce2250a59 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/variables/secondImport/zarf.yaml @@ -0,0 +1,18 @@ +kind: ZarfPackageConfig +metadata: + name: child-package +constants: + - name: PARENT_CONSTANT + value: "value from child in component imported later" + - name: CHILD_CONSTANT + value: "value from child in component imported later" +variables: + - name: PARENT_VAR + default: "default from child" + - name: CHILD_VAR + default: "default from child in component imported later" + - name: SECONDARY_CHILD_VAR + default: "default from child in component imported later" +components: + - name: component-from-different-package + required: true diff --git a/src/pkg/packager/load/testdata/import/import/variables/zarf.yaml b/src/pkg/packager/load/testdata/import/import/variables/zarf.yaml new file mode 100644 index 0000000000..79697a5522 --- /dev/null +++ b/src/pkg/packager/load/testdata/import/import/variables/zarf.yaml @@ -0,0 +1,22 @@ +kind: ZarfPackageConfig +metadata: + name: parent-package +constants: + - name: PARENT_CONSTANT + value: "value from parent" +variables: + - name: PARENT_VAR + default: "default from parent" +components: + - name: first-imported-component + required: true + import: + path: import + - name: same-package-imported-again + required: true + import: + path: import + - name: component-from-different-package + required: true + import: + path: secondImport