diff --git a/README.md b/README.md
index 8f49de8ee0..4593158b2c 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@ Zarf eliminates the [complexity of air gap software delivery](https://www.itopst
## 🛠️ Configurable Features
-- Customizable [variables and package templates](https://docs.zarf.dev/ref/variables/) with defaults and user prompting
+- Customizable [variables and package templates](https://docs.zarf.dev/ref/values/) with defaults and user prompting
- [Composable packages](https://docs.zarf.dev/ref/components/#component-imports) to include multiple sub-packages/components
- Component-level OS/architecture filtering
@@ -67,7 +67,7 @@ To discover more about Zarf and explore its features, please visit [docs.zarf.de
- [packages](https://docs.zarf.dev/ref/packages)
- [components](https://docs.zarf.dev/ref/components)
- [actions](https://docs.zarf.dev/ref/actions)
-- [variables](https://docs.zarf.dev/ref/variables)
+- [variables](https://docs.zarf.dev/ref/values)
- [SBOMs](https://docs.zarf.dev/ref/sboms)
- and more!
diff --git a/hack/check-zarf-docs-and-schema.sh b/hack/check-zarf-docs-and-schema.sh
index 93f4e4be0e..216d64b0ea 100755
--- a/hack/check-zarf-docs-and-schema.sh
+++ b/hack/check-zarf-docs-and-schema.sh
@@ -1,9 +1,9 @@
#!/usr/bin/env sh
-if [ -z "$(git status -s docs/ zarf.schema.json)" ]; then
+if [ -z "$(git status -s ./site/src/content/docs/commands/ ./zarf.schema.json)" ]; then
echo "Success!"
exit 0
else
- git diff docs/ zarf.schema.json
+ git diff ./site/src/content/docs/commands/ ./zarf.schema.json
exit 1
fi
diff --git a/site/src/assets/what-is-zarf/appliance.drawio.png b/site/src/assets/what-is-zarf/appliance.drawio.png
deleted file mode 100644
index 13ccfe81cc..0000000000
Binary files a/site/src/assets/what-is-zarf/appliance.drawio.png and /dev/null differ
diff --git a/site/src/assets/what-is-zarf/existing-cluster.drawio.png b/site/src/assets/what-is-zarf/existing-cluster.drawio.png
deleted file mode 100644
index b6fee8f4d0..0000000000
Binary files a/site/src/assets/what-is-zarf/existing-cluster.drawio.png and /dev/null differ
diff --git a/site/src/assets/what-is-zarf/how-to-use-zarf.drawio.png b/site/src/assets/what-is-zarf/how-to-use-zarf.drawio.png
deleted file mode 100644
index 7b62e58243..0000000000
Binary files a/site/src/assets/what-is-zarf/how-to-use-zarf.drawio.png and /dev/null differ
diff --git a/site/src/assets/what-is-zarf/utility-cluster.drawio.png b/site/src/assets/what-is-zarf/utility-cluster.drawio.png
deleted file mode 100644
index 26f289ea9f..0000000000
Binary files a/site/src/assets/what-is-zarf/utility-cluster.drawio.png and /dev/null differ
diff --git a/site/src/assets/zarf-bubbles.svg b/site/src/assets/zarf-bubbles.svg
index db3cafa5ba..8381dd3501 100644
--- a/site/src/assets/zarf-bubbles.svg
+++ b/site/src/assets/zarf-bubbles.svg
@@ -1,12 +1,12 @@
+ inkscape:current-layer="svg385" />
+ id="g239"
+ transform="matrix(1.9997122,0,0,1.9832754,0.21874591,2.675931)">
+ id="rect1"
+ x="0"
+ y="0"
+ style="fill:url(#paint0_radial_260_33984)" />
+ id="path1"
+ style="fill:url(#paint1_linear_260_33984)" />
+ id="path2"
+ style="fill:url(#paint2_linear_260_33984)" />
+ id="path10"
+ style="fill:url(#paint10_linear_260_33984)" />
@@ -1167,70 +1174,72 @@
+ id="path118"
+ style="fill:url(#paint17_linear_260_33984)" />
+ id="path126"
+ style="fill:url(#paint22_linear_260_33984)" />
+ id="path138"
+ style="fill:url(#paint24_linear_260_33984)" />
+ id="path139"
+ style="fill:url(#paint25_linear_260_33984)" />
+ id="path140"
+ style="fill:url(#paint26_linear_260_33984)" />
+ id="path141"
+ style="fill:url(#paint27_linear_260_33984)" />
+ id="path142"
+ style="fill:url(#paint28_linear_260_33984)" />
+ id="path143"
+ style="fill:url(#paint29_linear_260_33984)" />
+ id="path144"
+ style="fill:url(#paint30_linear_260_33984)" />
+ id="path146"
+ style="fill:url(#paint32_linear_260_33984)" />
+ id="path154"
+ style="fill:url(#paint37_linear_260_33984)" />
+ id="path155"
+ style="fill:url(#paint38_linear_260_33984)" />
+ id="path160"
+ style="fill:url(#paint41_linear_260_33984)" />
+ id="path222"
+ style="fill:url(#paint51_linear_260_33984)" />
@@ -1989,7 +2010,7 @@
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
- gradientTransform="translate(380 80) rotate(90) scale(80 380)">
+ gradientTransform="matrix(0,80,-380,0,380,80)">
@@ -2027,10 +2048,10 @@
@@ -2173,9 +2194,9 @@
@@ -2242,9 +2263,9 @@
@@ -2275,10 +2296,10 @@
@@ -2310,9 +2331,9 @@
@@ -2347,7 +2368,7 @@
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
- gradientTransform="translate(290.309 151.696) rotate(-90.2101) scale(28.0849 214.546)">
+ gradientTransform="matrix(-0.10298532,-28.084711,214.54456,-0.78672485,290.309,151.696)">
@@ -2357,9 +2378,9 @@
@@ -2417,9 +2438,9 @@
@@ -2938,9 +2959,9 @@
+ fill="#ffffff"
+ id="rect384"
+ x="0"
+ y="0" />
+ fill="#ffffff"
+ transform="translate(0,-125)"
+ id="rect385"
+ x="0"
+ y="0" />
{
if (!include) {
@@ -16,6 +16,21 @@ const json = await import("../assets/zarf.schema.json");
// @ts-expect-error - We don't import a TS type for the schema, but we know it's structured correctly
const itemSchema = json.definitions[item];
+if (unwrap) {
+ unwrap.forEach((wrapped: string) => {
+ if (itemSchema.properties[wrapped]) {
+ // @ts-expect-error - We don't import a TS type for the schema, but we know it's structured correctly
+ const wrappedSchema = json.definitions[wrapped];
+
+ delete itemSchema.properties[wrapped]
+ itemSchema.required = itemSchema.required.filter((elem: string) => elem != wrapped)
+
+ itemSchema.properties = {...wrappedSchema.properties, ...itemSchema.properties}
+ itemSchema.required = [...wrappedSchema.required, ...itemSchema.required]
+ }
+ });
+}
+
const properties = Object.keys(itemSchema.properties)
.filter(includesElement)
.sort()
diff --git a/site/src/content/docs/faq.mdx b/site/src/content/docs/faq.mdx
index 024399c23e..1e662a262a 100644
--- a/site/src/content/docs/faq.mdx
+++ b/site/src/content/docs/faq.mdx
@@ -144,4 +144,4 @@ Typically you should not deploy a Zarf package in YOLO mode if the cluster has a
A `skeleton` package is a bare-bones Zarf package definition alongside its associated local files and manifests that has been published to an OCI registry. These packages are intended for use with [component composability](/ref/components) to provide versioned imports for components that you wish to mix and match or modify with merge-overrides across multiple separate packages.
-Skeleton packages have not been run through the `zarf package create` process yet, and thus do not have any remote resources included (no images, repos, or remote manifests and files) thereby retaining any [create-time package configuration templates](/ref/variables) as they were defined in the original `zarf.yaml` (i.e. untemplated).
+Skeleton packages have not been run through the `zarf package create` process yet, and thus do not have any remote resources included (no images, repos, or remote manifests and files) thereby retaining any [create-time package configuration templates](/ref/values) as they were defined in the original `zarf.yaml` (i.e. untemplated).
diff --git a/site/src/content/docs/ref/components.mdx b/site/src/content/docs/ref/components.mdx
index 1eaa0bcfb4..aff22ada6e 100644
--- a/site/src/content/docs/ref/components.mdx
+++ b/site/src/content/docs/ref/components.mdx
@@ -117,7 +117,7 @@ Zarf dynamically generates a Helm Chart from the named manifest entries that you
:::note
-Kustomizations are handled a bit differently than normal manifests in that Zarf will automatically run `kustomize build` on them during `zarf package create`, thus rendering the Kustomization into a single manifest file. This prevents needing to grab any remote Kustomization resources during `zarf package deploy` but also means that any Zarf [`variables`](/ref/variables/) will only apply to the rendered manifest not the `kustomize build` process.
+Kustomizations are handled a bit differently than normal manifests in that Zarf will automatically run `kustomize build` on them during `zarf package create`, thus rendering the Kustomization into a single manifest file. This prevents needing to grab any remote Kustomization resources during `zarf package deploy` but also means that any Zarf [`variables`](/ref/values/) will only apply to the rendered manifest not the `kustomize build` process.
:::
@@ -222,7 +222,7 @@ The `import` key in Zarf supports two modes to pull in a component:
:::caution
-The import `path` or `url` must be statically defined at create time. You cannot use [package templates](/ref/variables/#create-time-package-configuration-templates) within them.
+The import `path` or `url` must be statically defined at create time. You cannot use [package templates](/ref/create/#package-templates) within them.
:::
diff --git a/site/src/content/docs/ref/create.mdx b/site/src/content/docs/ref/create.mdx
index b53ea157bc..422a887035 100644
--- a/site/src/content/docs/ref/create.mdx
+++ b/site/src/content/docs/ref/create.mdx
@@ -96,3 +96,46 @@ You do not need to create init configs by yourself unless you want to customize
To deploy a Zarf Package, you can use the command `zarf package deploy`. This will prompt you to select from all of the files in your current directory that match the name `zarf-package-*.tar.zst`. Alternatively, if you already know which package you want to deploy, you can simply use the command `zarf package deploy {PACKAGE_NAME}`.
During the deployment process, Zarf will leverage the infrastructure created during the 'init' process (such as the Docker registry and Git server) to push all the necessary images and repositories required for the package to operate.
+
+
+### Package Templates
+
+:::caution
+
+`zarf package create` templates only template `###ZARF_PKG_TMPL_*###` entries the `zarf.yaml` file while `zarf package deploy` only templates other `manifests`, `charts`, `files`, and `actions`. To learn more about using deployment values see the [Deployment Values](/ref/values) page.
+
+:::
+
+You can also specify `zarf.yaml` package configuration templates at package create time by including `###_ZARF_PKG_TMPL_*###` as the value for any string-type data in your package definition. These values are discovered during `zarf package create` and will always be prompted for if not using `--confirm` or `--set`. An example of this is below:
+
+```yaml
+kind: ZarfPackageConfig
+metadata:
+ name: 'pkg-variables'
+ description: 'Prompt for a variables during package create'
+
+constants:
+ - name: PROMPT_IMAGE
+ value: '###ZARF_PKG_TMPL_PROMPT_ON_CREATE###'
+
+components:
+ - name: zarf-prompt-image
+ required: true
+ images:
+ - '###ZARF_PKG_TMPL_PROMPT_ON_CREATE###'
+```
+
+:::caution
+
+It is not recommended to use package configuration templates for any `sensitive` data as this will be baked into the package as plain text. Please use a deploy-time variable with the `sensitive` key set instead.
+
+:::
+
+:::note
+
+You can only template string values in this way as non-string values will not marshal/unmarshal properly through the yaml.
+
+Additionally, you cannot template the component import path using package configuration templates
+
+:::
+
diff --git a/site/src/content/docs/ref/values.mdx b/site/src/content/docs/ref/values.mdx
new file mode 100644
index 0000000000..e356501d14
--- /dev/null
+++ b/site/src/content/docs/ref/values.mdx
@@ -0,0 +1,151 @@
+---
+title: Deployment Values
+sidebar:
+ order: 35
+---
+
+import Properties from '@components/SchemaItemProperties.astro';
+import ExampleYAML from "@components/ExampleYAML.astro";
+
+Deploy time values are used throughout the Zarf deployment process to template `manifests` and `files`, set Helm values, or provide environment variables for `actions`, and can be provided by the `zarf package deploy` user, the `zarf package create` user, or internally by Zarf itself.
+
+## Using Values
+
+### Value Templates
+
+Values can be templated into `manifests`, `files`, and `charts` using a unique `###ZARF_###` syntax anywhere in the file, where `` is the name of the value along with any associated prefix in ALL_CAPS (see [Setting Values](#setting-values) below). This allows you to punch through other templating engines to place values precisely where you want in a given file. You can also control how this templating happens when defining a value such as with the `autoIndent` key on `constants` and `variables`. A simple value template for a [Zarf Variable](#variables-zarf_var_) named `DATABASE_USERNAME` would look like the following:
+
+```yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: db-configmap
+data:
+ username: ###ZARF_VAR_DATABASE_USERNAME###
+```
+
+### Helm Chart Mapping
+
+[Zarf Variables](#variables-zarf_var_) can also be mapped directly to Helm values within a given `charts` definition. This is done with the `variables` key within a chart that allows you to take a Zarf Variable `name` and map it to a YAML path within that chart's Helm values. This chart's Helm value will then be set to the current value of the Zarf Variable at the time of it's installation.
+
+```yaml
+ charts:
+ - name: wordpress
+ version: 16.0.4
+ namespace: wordpress
+ localPath: chart
+ variables:
+ - name: DATABASE_USERNAME
+ path: db.username
+```
+
+
+
+:::caution
+
+Chart `variables` in Zarf are currently an `alpha` feature and may be subject to change in later versions of Zarf.
+
+:::
+
+### Environment Variables
+
+Zarf `actions` can also pull values from the shell's environment when running a `cmd`. These values are available under the same `ZARF_` as value templates (without any `#`s) and can be used like the below:
+
+```yaml
+ actions:
+ onDeploy:
+ after:
+ - cmd: echo ${ZARF_VAR_DATABASE_USERNAME}
+```
+
+## Setting Values
+
+:::note
+
+All value `name` fields must match the regex pattern `^[A-Z0-9_]+$` ([Test](https://regex101.com/r/BG5ZqW/1)).
+
+:::
+
+### Variables (`ZARF_VAR_`)
+
+Variables are dynamic values that are set by the `zarf package deploy` user or internally by the outputs of `actions`. When used they are prefixed with `ZARF_VAR`, and they can be defined with the top-level `variables` key for input by the user:
+
+```yaml
+variables:
+ name: DATABASE_USERNAME
+ description: 'The username for the database'
+```
+
+
+
+Or can be set within an `actions` `setVariables` key to take the value from the standard output of the given `cmd`:
+
+```yaml
+components:
+ - name: set-variable-example
+ actions:
+ onDeploy:
+ after:
+ - cmd: echo "username-value"
+ setVariables:
+ - name: DATABASE_USERNAME
+```
+
+
+
+:::note
+
+Variables with `type: file` will be set to the filepath when used in `actions` (see [Environment Variables](#environment-variables) above) due to constraints on the size of environment variables in the shell. This also allows for additional processing of the file by its filename.
+
+:::
+
+:::tip
+
+
+For user-specified variables, you can specify a `default` value for the variable to take in case a user does not provide one on deploy, and can specify whether to `prompt` the user for the variable when not using the `--confirm` or `--set` flags.
+
+```yaml
+variables:
+ name: DATABASE_USERNAME
+ default: 'postgres'
+ prompt: true
+```
+
+When not specifying `default`, `prompt`, `sensitive`, `autoIndent`, or `type` Zarf will default to `default: ""`, `prompt: false`, `sensitive: false`, `autoIndent: false`, and `type: "raw"`
+
+:::
+
+### Constants (`ZARF_CONST_`)
+
+Constants are static values that are set by the `zarf package create` user and are used as a way to bake in a common value that the package creator would like to template or use within the deployment process. They are useful to centralize the setting of resources that will be baked into the package (such as image references) to have a singular place to update potentially many downstream references. They are set with a top-level `constants` key as in the below:
+
+```yaml
+constants:
+ name: DATABASE_USERNAME
+ description: 'The username for the database'
+ value: 'postgres'
+```
+
+
+
+
+### Internal Values (`ZARF_`)
+
+In addition to user supplied Variables, and Constants, Zarf maintains a list of internal variables that components can use for more advanced functionality (such as within [`init` packages](/ref/init-package)). Below are the current values Zarf supports:
+
+- `STORAGE_CLASS`: Storage class specified for persistent storage within the Kubernetes cluster (maps to `--storage-class` on `zarf init`)
+- `REGISTRY`: Address of the registry server used during `zarf init` (maps to `--registry-url` on `zarf init`)
+- `NODEPORT`: Nodeport used for a registry internal to the cluster (maps to `--nodeport` on `zarf init`)
+- `REGISTRY_AUTH_PUSH`: Password for pushing images to the registry (maps to `--registry-push-password` on `zarf init`)
+- `REGISTRY_AUTH_PULL`: Password for pulling images from the registry (maps to `--registry-pull-password` on `zarf init`)
+- `GIT_PUSH`: Username utilized for pushing changes to the Git server (maps to `--git-push-username` on `zarf init`)
+- `GIT_AUTH_PUSH`: Password required for pushing changes to the Git server (maps to `--git-push-password` on `zarf init`)
+- `GIT_PULL`: Username employed for pulling changes from the Git server (maps to `--git-pull-username` on `zarf init`)
+- `GIT_AUTH_PULL`: Password required for pulling changes from the Git server (maps to `--git-pull-password` on `zarf init`)
+- `DATA_INJECTION_MARKER`: The marker used within a `dataInjection` target Pod `spec` that Zarf uses to track a data injection
+
+:::note
+
+Because files can be deployed without a Kubernetes cluster, some built-in values such as `###ZARF_REGISTRY###` may not be available if no previous component has required access to the cluster. If you need one of these built-in values, a prior component will need to have been called that requires access to the cluster, such as `images`, `repos`, `charts`, `manifests`, or `dataInjections`.
+
+:::
diff --git a/site/src/content/docs/ref/variables.mdx b/site/src/content/docs/ref/variables.mdx
deleted file mode 100644
index f649117081..0000000000
--- a/site/src/content/docs/ref/variables.mdx
+++ /dev/null
@@ -1,153 +0,0 @@
----
-title: Variables
-sidebar:
- order: 35
----
-
-import Properties from '@components/SchemaItemProperties.astro';
-import ExampleYAML from "@components/ExampleYAML.astro";
-
-:::note
-
-Because files can be deployed without a Kubernetes cluster, some built-in variables such as `###ZARF_REGISTRY###` may not be available if no previous component has required access to the cluster. If you need one of these built-in variables, a prior component will need to have been called that requires access to the cluster, such as `images`, `repos`, `manifests`, `dataInjections`.
-
-:::
-
-## Deploy-Time Variables and Constants
-
-To use variables and constants at deploy time you need to have two things:
-
-1. a manifest that you want to template a value in
-2. a defined variable in the `zarf.yaml` file from `variables` or `setVariable`
-
-The manifest should have your desired variable name in ALL CAPS prefixed with `###ZARF_VAR` for `variables` or prefixed with `###ZARF_CONST` for `constants` and suffixed with `###`. For example in a configmap that took a variable named `DATABASE_USERNAME` you would provide the following:
-
-```yaml
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: db-configmap
-data:
- username: ###ZARF_VAR_DATABASE_USERNAME###
-```
-
-In the `zarf.yaml`, you would need to define the variable in the `variables` section or as output from an action with `setVariable` with the same `name` as above. Or for a constant you would use the `constants` section. For the same example as above, you would have the following for a variable defined by the deploy user:
-
-```yaml
-variables:
- name: DATABASE_USERNAME
- description: 'The username for the database'
-```
-
-And the following for a variable defined as an output from an action:
-
-```yaml
-components:
- - name: set-variable-example
- actions:
- onDeploy:
- after:
- - cmd: echo "username-value"
- setVariables:
- - name: DATABASE_USERNAME
-```
-
-Zarf `variables` can also have additional fields that describe how Zarf will handle them which are described below:
-
-
-
-:::note
-
-Variables with `type: file` will be set to the filepath in `actions` due to constraints on the size of environment variables in the shell. This also allows for additional processing of the file by its filename.
-
-:::
-
-:::note
-
-The fields `default`, `description` and `prompt` are not available on `setVariables` since they always take the standard output of an action command and will not be interacted with directly by a deploy user.
-
-:::
-
-Zarf `constants` are similar but have fewer options as they are static by the time `zarf package deploy` is run:
-
-
-
-:::note
-
-All names must match the regex pattern `^[A-Z0-9_]+$` [Test](https://regex101.com/r/BG5ZqW/1)).
-
-:::
-
-:::tip
-
-When not specifying `default`, `prompt`, `sensitive`, `autoIndent`, or `type` Zarf will default to `default: ""`, `prompt: false`, `sensitive: false`, `autoIndent: false`, and `type: "raw"`
-
-:::
-
-For user-specified variables, you can also specify a `default` value for the variable to take in case a user does not provide one on deploy, and can specify whether to `prompt` the user for the variable when not using the `--confirm` or `--set` flags.
-
-```yaml
-variables:
- name: DATABASE_USERNAME
- default: 'postgres'
- prompt: true
-```
-
-:::note
-
-Variables that do not have a default, are not `--set` and are not prompted for during deploy will be replaced with an empty string in manifests/charts/files
-
-:::
-
-For constants, you must specify the value they will use at package create. These values cannot be overridden with `--set` during `zarf package deploy`, but you can use package template variables (described below) to variablize them during `zarf package create`.
-
-```yaml
-constants:
- name: DATABASE_TABLE
- value: 'users'
-```
-
-:::note
-
-`zarf package create` only templates the `zarf.yaml` file, and `zarf package deploy` only templates other manifests, charts and files
-
-:::
-
-## Create-Time Package Configuration Templates
-
-You can also specify package configuration templates at package create time by including `###_ZARF_PKG_TMPL_*###` as the value for any string-type data in your package definition. These values are discovered during `zarf package create` and will always be prompted for if not using `--confirm` or `--set`. An example of this is below:
-
-```yaml
-kind: ZarfPackageConfig
-metadata:
- name: 'pkg-variables'
- description: 'Prompt for a variables during package create'
-
-constants:
- - name: PROMPT_IMAGE
- value: '###ZARF_PKG_TMPL_PROMPT_ON_CREATE###'
-
-components:
- - name: zarf-prompt-image
- required: true
- images:
- - '###ZARF_PKG_TMPL_PROMPT_ON_CREATE###'
-```
-
-:::caution
-
-It is not recommended to use package configuration templates for any `sensitive` data as this will be baked into the package as plain text. Please use a deploy-time variable with the `sensitive` key set instead.
-
-:::
-
-:::note
-
-You can only template string values in this way as non-string values will not marshal/unmarshal properly through the yaml.
-
-:::
-
-:::note
-
-You cannot template the component import path using package configuration templates
-
-:::
diff --git a/site/src/content/docs/tutorials/0-creating-a-zarf-package.mdx b/site/src/content/docs/tutorials/0-creating-a-zarf-package.mdx
index 3cb69d2cb0..859c479056 100644
--- a/site/src/content/docs/tutorials/0-creating-a-zarf-package.mdx
+++ b/site/src/content/docs/tutorials/0-creating-a-zarf-package.mdx
@@ -120,7 +120,7 @@ Zarf has more `dev` commands you can learn about on the [dev CLI docs page](/ref
We now have a deployable package definition, but it is currently not very configurable and might not fit every environment we want to deploy it to. If we deployed it as-is we would always have a Zarf Blog and a `zarf` user with an autogenerated password.
-To resolve this, we can add configuration options with [Zarf Deploy-Time Variables](/ref/examples/variables/). For this package we will add a `variables` section to our `zarf.yaml` above `components` that will allow us to setup the user and the blog.
+To resolve this, we can add configuration options with [Zarf Variables](/ref/examples/values/#variables-zarf_var_). For this package we will add a `variables` section to our `zarf.yaml` above `components` that will allow us to setup the user and the blog.
```yaml
variables:
diff --git a/site/src/content/docs/tutorials/10-package-create-differential.mdx b/site/src/content/docs/tutorials/10-package-create-differential.mdx
index bd9f6c071b..176424805c 100644
--- a/site/src/content/docs/tutorials/10-package-create-differential.mdx
+++ b/site/src/content/docs/tutorials/10-package-create-differential.mdx
@@ -1,5 +1,5 @@
---
-title: Create Differential Packages with Zarf
+title: Create Differential Packages
sidebar:
order: 10
---
diff --git a/src/cmd/tools/zarf.go b/src/cmd/tools/zarf.go
index 54f5b18067..363fe87c63 100644
--- a/src/cmd/tools/zarf.go
+++ b/src/cmd/tools/zarf.go
@@ -18,6 +18,7 @@ import (
"github.com/defenseunicorns/zarf/src/config/lang"
"github.com/defenseunicorns/zarf/src/internal/packager/git"
"github.com/defenseunicorns/zarf/src/internal/packager/helm"
+ "github.com/defenseunicorns/zarf/src/internal/packager/template"
"github.com/defenseunicorns/zarf/src/pkg/cluster"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/packager/sources"
@@ -138,7 +139,7 @@ var updateCredsCmd = &cobra.Command{
}
// Update Zarf 'init' component Helm releases if present
- h := helm.NewClusterOnly(&types.PackagerConfig{State: newState}, c)
+ h := helm.NewClusterOnly(&types.PackagerConfig{}, template.GetZarfVariableConfig(), newState, c)
if slices.Contains(args, message.RegistryKey) && newState.RegistryInfo.InternalRegistry {
err = h.UpdateZarfRegistryValues()
diff --git a/src/extensions/bigbang/bigbang.go b/src/extensions/bigbang/bigbang.go
index 9445354046..e71954f7d0 100644
--- a/src/extensions/bigbang/bigbang.go
+++ b/src/extensions/bigbang/bigbang.go
@@ -18,6 +18,7 @@ import (
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/utils"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
"github.com/defenseunicorns/zarf/src/types/extensions"
fluxHelmCtrl "github.com/fluxcd/helm-controller/api/v2beta1"
@@ -94,7 +95,7 @@ func Run(YOLO bool, tmpPaths *layout.ComponentPaths, c types.ZarfComponent) (typ
},
path.Join(tmpPaths.Temp, bb),
path.Join(tmpPaths.Temp, bb, "values"),
- helm.WithPackageConfig(&types.PackagerConfig{}),
+ helm.WithVariableConfig(&variables.VariableConfig{}),
)
// Download the chart from Git and save it to a temporary directory.
diff --git a/src/internal/packager/helm/chart.go b/src/internal/packager/helm/chart.go
index 0e10c0ef99..72b80d65f9 100644
--- a/src/internal/packager/helm/chart.go
+++ b/src/internal/packager/helm/chart.go
@@ -44,12 +44,6 @@ func (h *Helm) InstallOrUpgradeChart() (types.ConnectStrings, string, error) {
h.chart.ReleaseName = h.chart.Name
}
- // Do not wait for the chart to be ready if data injections are present.
- if len(h.component.DataInjections) > 0 {
- spinner.Updatef("Data injections detected, not waiting for chart to be ready")
- h.chart.NoWait = true
- }
-
// Setup K8s connection.
err := h.createActionConfig(h.chart.Namespace, spinner)
if err != nil {
diff --git a/src/internal/packager/helm/common.go b/src/internal/packager/helm/common.go
index 335fbf0f6c..6fba4d364e 100644
--- a/src/internal/packager/helm/common.go
+++ b/src/internal/packager/helm/common.go
@@ -17,6 +17,7 @@ import (
"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/cluster"
"github.com/defenseunicorns/zarf/src/pkg/message"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart"
@@ -29,19 +30,20 @@ type Helm struct {
chartPath string
valuesPath string
- cfg *types.PackagerConfig
- component types.ZarfComponent
- cluster *cluster.Cluster
- timeout time.Duration
- retries int
+ cfg *types.PackagerConfig
+ cluster *cluster.Cluster
+ timeout time.Duration
+ retries int
kubeVersion string
chartOverride *chart.Chart
valuesOverrides map[string]any
- settings *cli.EnvSettings
- actionConfig *action.Configuration
+ settings *cli.EnvSettings
+ actionConfig *action.Configuration
+ variableConfig *variables.VariableConfig
+ state *types.ZarfState
}
// Modifier is a function that modifies the Helm config.
@@ -64,12 +66,14 @@ func New(chart types.ZarfChart, chartPath string, valuesPath string, mods ...Mod
}
// NewClusterOnly returns a new Helm config struct geared toward interacting with the cluster (not packages)
-func NewClusterOnly(cfg *types.PackagerConfig, cluster *cluster.Cluster) *Helm {
+func NewClusterOnly(cfg *types.PackagerConfig, variableConfig *variables.VariableConfig, state *types.ZarfState, cluster *cluster.Cluster) *Helm {
return &Helm{
- cfg: cfg,
- cluster: cluster,
- timeout: config.ZarfDefaultTimeout,
- retries: config.ZarfDefaultRetries,
+ cfg: cfg,
+ variableConfig: variableConfig,
+ state: state,
+ cluster: cluster,
+ timeout: config.ZarfDefaultTimeout,
+ retries: config.ZarfDefaultRetries,
}
}
@@ -133,10 +137,11 @@ func NewFromZarfManifest(manifest types.ZarfManifest, manifestPath, packageName,
}
// WithDeployInfo adds the necessary information to deploy a given chart
-func WithDeployInfo(component types.ZarfComponent, cfg *types.PackagerConfig, cluster *cluster.Cluster, valuesOverrides map[string]any, timeout time.Duration, retries int) Modifier {
+func WithDeployInfo(cfg *types.PackagerConfig, variableConfig *variables.VariableConfig, state *types.ZarfState, cluster *cluster.Cluster, valuesOverrides map[string]any, timeout time.Duration, retries int) Modifier {
return func(h *Helm) {
- h.component = component
h.cfg = cfg
+ h.variableConfig = variableConfig
+ h.state = state
h.cluster = cluster
h.valuesOverrides = valuesOverrides
h.timeout = timeout
@@ -151,10 +156,10 @@ func WithKubeVersion(kubeVersion string) Modifier {
}
}
-// WithPackageConfig sets the packager config for the chart
-func WithPackageConfig(cfg *types.PackagerConfig) Modifier {
+// WithVariableConfig sets the variable config for the chart
+func WithVariableConfig(variableConfig *variables.VariableConfig) Modifier {
return func(h *Helm) {
- h.cfg = cfg
+ h.variableConfig = variableConfig
}
}
diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go
index ed3dec5d9f..7cee486d99 100644
--- a/src/internal/packager/helm/post-render.go
+++ b/src/internal/packager/helm/post-render.go
@@ -13,7 +13,6 @@ import (
"github.com/defenseunicorns/pkg/helpers"
"github.com/defenseunicorns/zarf/src/config"
- "github.com/defenseunicorns/zarf/src/internal/packager/template"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/defenseunicorns/zarf/src/types"
@@ -29,22 +28,11 @@ type renderer struct {
*Helm
connectStrings types.ConnectStrings
namespaces map[string]*corev1.Namespace
- values template.Values
}
func (h *Helm) newRenderer() (*renderer, error) {
message.Debugf("helm.NewRenderer()")
- valueTemplate, err := template.Generate(h.cfg)
- if err != nil {
- return nil, err
- }
-
- // TODO (@austinabro321) this should be cleaned up after https://github.com/defenseunicorns/zarf/pull/2276 gets merged
- if h.cfg.State == nil {
- valueTemplate.SetState(&types.ZarfState{})
- }
-
namespaces := make(map[string]*corev1.Namespace)
if h.cluster != nil {
namespaces[h.chart.Namespace] = h.cluster.NewZarfManagedNamespace(h.chart.Namespace)
@@ -54,7 +42,6 @@ func (h *Helm) newRenderer() (*renderer, error) {
Helm: h,
connectStrings: make(types.ConnectStrings),
namespaces: namespaces,
- values: *valueTemplate,
}, nil
}
@@ -71,7 +58,7 @@ func (r *renderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) {
}
// Run the template engine against the chart output
- if _, err := template.ProcessYamlFilesInPath(tempDir, r.component, r.values); err != nil {
+ if err := r.variableConfig.ReplaceTextTemplate(path); err != nil {
return nil, fmt.Errorf("error templating the helm chart: %w", err)
}
@@ -143,12 +130,12 @@ func (r *renderer) adoptAndUpdateNamespaces() error {
}
// If the package is marked as YOLO and the state is empty, skip the secret creation for this namespace
- if r.cfg.Pkg.Metadata.YOLO && r.cfg.State.Distro == "YOLO" {
+ if r.cfg.Pkg.Metadata.YOLO && r.state.Distro == "YOLO" {
continue
}
// Create the secret
- validRegistrySecret := c.GenerateRegistryPullCreds(name, config.ZarfImagePullSecretName, r.cfg.State.RegistryInfo)
+ validRegistrySecret := c.GenerateRegistryPullCreds(name, config.ZarfImagePullSecretName, r.state.RegistryInfo)
// Try to get a valid existing secret
currentRegistrySecret, _ := c.GetSecret(name, config.ZarfImagePullSecretName)
@@ -159,7 +146,7 @@ func (r *renderer) adoptAndUpdateNamespaces() error {
}
// Generate the git server secret
- gitServerSecret := c.GenerateGitPullCreds(name, config.ZarfGitServerSecretName, r.cfg.State.GitServer)
+ gitServerSecret := c.GenerateGitPullCreds(name, config.ZarfGitServerSecretName, r.state.GitServer)
// Create or update the zarf git server secret
if _, err := c.CreateOrUpdateSecret(gitServerSecret); err != nil {
diff --git a/src/internal/packager/helm/repo.go b/src/internal/packager/helm/repo.go
index d91349a5c6..97582a64b9 100644
--- a/src/internal/packager/helm/repo.go
+++ b/src/internal/packager/helm/repo.go
@@ -376,7 +376,7 @@ func (h *Helm) listAvailableChartsAndVersions(pull *action.Pull) error {
versions += entry.Version + separator
}
- versions = message.Truncate(versions, 75, false)
+ versions = helpers.Truncate(versions, 75, false)
chartData = append(chartData, []string{name, versions})
}
diff --git a/src/internal/packager/helm/zarf.go b/src/internal/packager/helm/zarf.go
index b8d42c3f84..c6db1299eb 100644
--- a/src/internal/packager/helm/zarf.go
+++ b/src/internal/packager/helm/zarf.go
@@ -7,23 +7,25 @@ package helm
import (
"fmt"
+ "github.com/defenseunicorns/zarf/src/internal/packager/template"
"github.com/defenseunicorns/zarf/src/pkg/cluster"
"github.com/defenseunicorns/zarf/src/pkg/k8s"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/transform"
"github.com/defenseunicorns/zarf/src/pkg/utils"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
"helm.sh/helm/v3/pkg/action"
)
// UpdateZarfRegistryValues updates the Zarf registry deployment with the new state values
func (h *Helm) UpdateZarfRegistryValues() error {
- pushUser, err := utils.GetHtpasswdString(h.cfg.State.RegistryInfo.PushUsername, h.cfg.State.RegistryInfo.PushPassword)
+ pushUser, err := utils.GetHtpasswdString(h.state.RegistryInfo.PushUsername, h.state.RegistryInfo.PushPassword)
if err != nil {
return fmt.Errorf("error generating htpasswd string: %w", err)
}
- pullUser, err := utils.GetHtpasswdString(h.cfg.State.RegistryInfo.PullUsername, h.cfg.State.RegistryInfo.PullPassword)
+ pullUser, err := utils.GetHtpasswdString(h.state.RegistryInfo.PullUsername, h.state.RegistryInfo.PullPassword)
if err != nil {
return fmt.Errorf("error generating htpasswd string: %w", err)
}
@@ -90,10 +92,7 @@ func (h *Helm) UpdateZarfAgentValues() error {
Namespace: "zarf",
ReleaseName: release.Name,
}
- h.component = types.ZarfComponent{
- Name: "zarf-agent",
- }
- h.cfg.Pkg.Constants = []types.ZarfPackageConstant{
+ h.variableConfig.SetConstants([]variables.Constant{
{
Name: "AGENT_IMAGE",
Value: currentAgentImage.Path,
@@ -102,9 +101,14 @@ func (h *Helm) UpdateZarfAgentValues() error {
Name: "AGENT_IMAGE_TAG",
Value: currentAgentImage.Tag,
},
+ })
+ applicationTemplates, err := template.GetZarfTemplates("zarf-agent", h.state)
+ if err != nil {
+ return fmt.Errorf("error setting up the templates: %w", err)
}
+ h.variableConfig.SetApplicationTemplates(applicationTemplates)
- err := h.UpdateReleaseValues(map[string]interface{}{})
+ err = h.UpdateReleaseValues(map[string]interface{}{})
if err != nil {
return fmt.Errorf("error updating the release values: %w", err)
}
diff --git a/src/internal/packager/images/push.go b/src/internal/packager/images/push.go
index 5daff0a14f..900b925651 100644
--- a/src/internal/packager/images/push.go
+++ b/src/internal/packager/images/push.go
@@ -91,7 +91,7 @@ func (i *ImageConfig) PushToZarfRegistry() error {
}
for refInfo, img := range refInfoToImage {
- refTruncated := message.Truncate(refInfo.Reference, 55, true)
+ refTruncated := helpers.Truncate(refInfo.Reference, 55, true)
progressBar.UpdateTitle(fmt.Sprintf("Pushing %s", refTruncated))
// If this is not a no checksum image push it for use with the Zarf agent
diff --git a/src/internal/packager/template/template.go b/src/internal/packager/template/template.go
index 19eed3e93c..f823c567f8 100644
--- a/src/internal/packager/template/template.go
+++ b/src/internal/packager/template/template.go
@@ -5,96 +5,52 @@
package template
import (
- "bufio"
"encoding/base64"
"fmt"
- "os"
- "regexp"
+ "log/slog"
"strings"
"github.com/defenseunicorns/zarf/src/types"
"github.com/defenseunicorns/pkg/helpers"
"github.com/defenseunicorns/zarf/src/config"
+ "github.com/defenseunicorns/zarf/src/pkg/interactive"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/utils"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
)
-// TextTemplate represents a value to be templated into a text file.
-type TextTemplate struct {
- Sensitive bool
- AutoIndent bool
- Type types.VariableType
- Value string
-}
-
-// Values contains the values to be used in the template.
-type Values struct {
- config *types.PackagerConfig
- htpasswd string
-}
-
-// Generate returns a Values struct with the values to be used in the template.
-func Generate(cfg *types.PackagerConfig) (*Values, error) {
- message.Debug("template.Generate()")
- var generated Values
-
- if cfg == nil {
- return nil, fmt.Errorf("config is nil")
- }
-
- generated.config = cfg
-
- if cfg.State == nil {
- return &generated, nil
- }
-
- regInfo := cfg.State.RegistryInfo
-
- // Only calculate this for internal registries to allow longer external passwords
- if regInfo.InternalRegistry {
- pushUser, err := utils.GetHtpasswdString(regInfo.PushUsername, regInfo.PushPassword)
- if err != nil {
- return nil, fmt.Errorf("error generating htpasswd string: %w", err)
- }
+const (
+ depMarkerOld = "DATA_INJECTON_MARKER"
+ depMarkerNew = "DATA_INJECTION_MARKER"
+)
- pullUser, err := utils.GetHtpasswdString(regInfo.PullUsername, regInfo.PullPassword)
- if err != nil {
- return nil, fmt.Errorf("error generating htpasswd string: %w", err)
+// GetZarfVariableConfig gets a variable configuration specific to Zarf
+func GetZarfVariableConfig() *variables.VariableConfig {
+ prompt := func(variable variables.InteractiveVariable) (value string, err error) {
+ if config.CommonOptions.Confirm {
+ return variable.Default, nil
}
-
- generated.htpasswd = fmt.Sprintf("%s\\n%s", pushUser, pullUser)
+ return interactive.PromptVariable(variable)
}
- return &generated, nil
+ return variables.New(
+ "zarf",
+ deprecatedKeys(),
+ prompt,
+ slog.New(message.ZarfHandler{}))
}
-// Ready returns true if the Values struct is ready to be used in the template.
-func (values *Values) Ready() bool {
- return values.config.State != nil
-}
+// GetZarfTemplates returns the template keys and values to be used for templating.
+func GetZarfTemplates(componentName string, state *types.ZarfState) (templateMap map[string]*variables.TextTemplate, err error) {
+ templateMap = make(map[string]*variables.TextTemplate)
-// SetState sets the state
-func (values *Values) SetState(state *types.ZarfState) {
- values.config.State = state
-}
-
-// GetVariables returns the variables to be used in the template.
-func (values *Values) GetVariables(component types.ZarfComponent) (templateMap map[string]*TextTemplate, deprecations map[string]string) {
- templateMap = make(map[string]*TextTemplate)
-
- depMarkerOld := "DATA_INJECTON_MARKER"
- depMarkerNew := "DATA_INJECTION_MARKER"
- deprecations = map[string]string{
- fmt.Sprintf("###ZARF_%s###", depMarkerOld): fmt.Sprintf("###ZARF_%s###", depMarkerNew),
- }
-
- if values.config.State != nil {
- regInfo := values.config.State.RegistryInfo
- gitInfo := values.config.State.GitServer
+ if state != nil {
+ regInfo := state.RegistryInfo
+ gitInfo := state.GitServer
builtinMap := map[string]string{
- "STORAGE_CLASS": values.config.State.StorageClass,
+ "STORAGE_CLASS": state.StorageClass,
// Registry info
"REGISTRY": regInfo.Address,
@@ -109,34 +65,35 @@ func (values *Values) GetVariables(component types.ZarfComponent) (templateMap m
"GIT_AUTH_PULL": gitInfo.PullPassword,
}
- // Include the data injection marker template if the component has data injections
- if len(component.DataInjections) > 0 {
- // Preserve existing misspelling for backwards compatibility
- builtinMap[depMarkerOld] = config.GetDataInjectionMarker()
- builtinMap[depMarkerNew] = config.GetDataInjectionMarker()
- }
+ // Preserve existing misspelling for backwards compatibility
+ builtinMap[depMarkerOld] = config.GetDataInjectionMarker()
+ builtinMap[depMarkerNew] = config.GetDataInjectionMarker()
// Don't template component-specific variables for every component
- switch component.Name {
+ switch componentName {
case "zarf-agent":
- agentTLS := values.config.State.AgentTLS
+ agentTLS := state.AgentTLS
builtinMap["AGENT_CRT"] = base64.StdEncoding.EncodeToString(agentTLS.Cert)
builtinMap["AGENT_KEY"] = base64.StdEncoding.EncodeToString(agentTLS.Key)
builtinMap["AGENT_CA"] = base64.StdEncoding.EncodeToString(agentTLS.CA)
case "zarf-seed-registry", "zarf-registry":
builtinMap["SEED_REGISTRY"] = fmt.Sprintf("%s:%s", helpers.IPV4Localhost, config.ZarfSeedPort)
- builtinMap["HTPASSWD"] = values.htpasswd
+ htpasswd, err := generateHtpasswd(®Info)
+ if err != nil {
+ return templateMap, err
+ }
+ builtinMap["HTPASSWD"] = htpasswd
builtinMap["REGISTRY_SECRET"] = regInfo.Secret
case "logging":
- builtinMap["LOGGING_AUTH"] = values.config.State.LoggingSecret
+ builtinMap["LOGGING_AUTH"] = state.LoggingSecret
}
// Iterate over any custom variables and add them to the mappings for templating
for key, value := range builtinMap {
// Builtin keys are always uppercase in the format ###ZARF_KEY###
- templateMap[strings.ToUpper(fmt.Sprintf("###ZARF_%s###", key))] = &TextTemplate{
+ templateMap[strings.ToUpper(fmt.Sprintf("###ZARF_%s###", key))] = &variables.TextTemplate{
Value: value,
}
@@ -149,131 +106,39 @@ func (values *Values) GetVariables(component types.ZarfComponent) (templateMap m
}
}
- for key, variable := range values.config.SetVariableMap {
- // Variable keys are always uppercase in the format ###ZARF_VAR_KEY###
- templateMap[strings.ToUpper(fmt.Sprintf("###ZARF_VAR_%s###", key))] = &TextTemplate{
- Value: variable.Value,
- Sensitive: variable.Sensitive,
- AutoIndent: variable.AutoIndent,
- Type: variable.Type,
- }
- }
-
- for _, constant := range values.config.Pkg.Constants {
- // Constant keys are always uppercase in the format ###ZARF_CONST_KEY###
- templateMap[strings.ToUpper(fmt.Sprintf("###ZARF_CONST_%s###", constant.Name))] = &TextTemplate{
- Value: constant.Value,
- AutoIndent: constant.AutoIndent,
- }
- }
-
debugPrintTemplateMap(templateMap)
- message.Debugf("deprecations = %#v", deprecations)
- return templateMap, deprecations
+ return templateMap, nil
}
-// Apply renders the template and writes the result to the given path.
-func (values *Values) Apply(component types.ZarfComponent, path string, ignoreReady bool) error {
- // If Apply() is called before all values are loaded, fail unless ignoreReady is true
- if !values.Ready() && !ignoreReady {
- return fmt.Errorf("template.Apply() called before template.Generate()")
+// deprecatedKeys returns a map of template keys that are deprecated
+func deprecatedKeys() map[string]string {
+ return map[string]string{
+ fmt.Sprintf("###ZARF_%s###", depMarkerOld): fmt.Sprintf("###ZARF_%s###", depMarkerNew),
}
-
- templateMap, deprecations := values.GetVariables(component)
- err := ReplaceTextTemplate(path, templateMap, deprecations, "###ZARF_[A-Z0-9_]+###")
-
- return err
}
-// ReplaceTextTemplate loads a file from a given path, replaces text in it and writes it back in place.
-func ReplaceTextTemplate(path string, mappings map[string]*TextTemplate, deprecations map[string]string, templateRegex string) error {
- textFile, err := os.Open(path)
- if err != nil {
- return err
- }
-
- // This regex takes a line and parses the text before and after a discovered template: https://regex101.com/r/ilUxAz/1
- regexTemplateLine := regexp.MustCompile(fmt.Sprintf("(?P.*?)(?P%s)(?P.*)", templateRegex))
-
- fileScanner := bufio.NewScanner(textFile)
-
- // Set the buffer to 1 MiB to handle long lines (i.e. base64 text in a secret)
- // 1 MiB is around the documented maximum size for secrets and configmaps
- const maxCapacity = 1024 * 1024
- buf := make([]byte, maxCapacity)
- fileScanner.Buffer(buf, maxCapacity)
-
- // Set the scanner to split on new lines
- fileScanner.Split(bufio.ScanLines)
-
- text := ""
-
- for fileScanner.Scan() {
- line := fileScanner.Text()
-
- for {
- matches := regexTemplateLine.FindStringSubmatch(line)
-
- // No template left on this line so move on
- if len(matches) == 0 {
- text += fmt.Sprintln(line)
- break
- }
-
- preTemplate := matches[regexTemplateLine.SubexpIndex("preTemplate")]
- templateKey := matches[regexTemplateLine.SubexpIndex("template")]
-
- _, present := deprecations[templateKey]
- if present {
- message.Warnf("This Zarf Package uses a deprecated variable: '%s' changed to '%s'. Please notify your package creator for an update.", templateKey, deprecations[templateKey])
- }
-
- template := mappings[templateKey]
-
- // Check if the template is nil (present), use the original templateKey if not (so that it is not replaced).
- value := templateKey
- if template != nil {
- value = template.Value
-
- // Check if the value is a file type and load the value contents from the file
- if template.Type == types.FileVariableType && value != "" {
- if isText, err := helpers.IsTextFile(value); err != nil || !isText {
- message.Warnf("Refusing to load a non-text file for templating %s", templateKey)
- line = matches[regexTemplateLine.SubexpIndex("postTemplate")]
- continue
- }
-
- contents, err := os.ReadFile(value)
- if err != nil {
- message.Warnf("Unable to read file for templating - skipping: %s", err.Error())
- line = matches[regexTemplateLine.SubexpIndex("postTemplate")]
- continue
- }
-
- value = string(contents)
- }
-
- // Check if the value is autoIndented and add the correct spacing
- if template.AutoIndent {
- indent := fmt.Sprintf("\n%s", strings.Repeat(" ", len(preTemplate)))
- value = strings.ReplaceAll(value, "\n", indent)
- }
- }
-
- // Add the processed text and continue processing the line
- text += fmt.Sprintf("%s%s", preTemplate, value)
- line = matches[regexTemplateLine.SubexpIndex("postTemplate")]
+// generateHtpasswd returns an htpasswd string for the current state's RegistryInfo.
+func generateHtpasswd(regInfo *types.RegistryInfo) (string, error) {
+ // Only calculate this for internal registries to allow longer external passwords
+ if regInfo.InternalRegistry {
+ pushUser, err := utils.GetHtpasswdString(regInfo.PushUsername, regInfo.PushPassword)
+ if err != nil {
+ return "", fmt.Errorf("error generating htpasswd string: %w", err)
}
- }
- textFile.Close()
+ pullUser, err := utils.GetHtpasswdString(regInfo.PullUsername, regInfo.PullPassword)
+ if err != nil {
+ return "", fmt.Errorf("error generating htpasswd string: %w", err)
+ }
- return os.WriteFile(path, []byte(text), helpers.ReadWriteUser)
+ return fmt.Sprintf("%s\\n%s", pushUser, pullUser), nil
+ }
+ return "", nil
}
-func debugPrintTemplateMap(templateMap map[string]*TextTemplate) {
+func debugPrintTemplateMap(templateMap map[string]*variables.TextTemplate) {
debugText := "templateMap = { "
for key, template := range templateMap {
diff --git a/src/internal/packager/template/yaml.go b/src/internal/packager/template/yaml.go
deleted file mode 100644
index 47c2db56f1..0000000000
--- a/src/internal/packager/template/yaml.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-FileCopyrightText: 2021-Present The Zarf Authors
-
-// Package template provides functions for templating yaml files.
-package template
-
-import (
- "regexp"
-
- "github.com/defenseunicorns/pkg/helpers"
- "github.com/defenseunicorns/zarf/src/types"
-)
-
-// ProcessYamlFilesInPath iterates over all yaml files in a given path and performs Zarf templating + image swapping.
-func ProcessYamlFilesInPath(path string, component types.ZarfComponent, values Values) ([]string, error) {
- // Only pull in yml and yaml files
- pattern := regexp.MustCompile(`(?mi)\.ya?ml$`)
- manifests, _ := helpers.RecursiveFileList(path, pattern, false)
-
- for _, manifest := range manifests {
- if err := values.Apply(component, manifest, false); err != nil {
- return nil, err
- }
- }
-
- return manifests, nil
-}
diff --git a/src/internal/packager/validate/validate.go b/src/internal/packager/validate/validate.go
index 83eba2dd07..48452929a1 100644
--- a/src/internal/packager/validate/validate.go
+++ b/src/internal/packager/validate/validate.go
@@ -13,6 +13,7 @@ import (
"github.com/defenseunicorns/pkg/helpers"
"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/config/lang"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
)
@@ -296,7 +297,7 @@ func validatePackageName(subject string) error {
return nil
}
-func validatePackageVariable(subject types.ZarfPackageVariable) error {
+func validatePackageVariable(subject variables.InteractiveVariable) error {
// ensure the variable name is only capitals and underscores
if !IsUppercaseNumberUnderscore(subject.Name) {
return fmt.Errorf(lang.PkgValidateMustBeUppercase, subject.Name)
@@ -305,7 +306,7 @@ func validatePackageVariable(subject types.ZarfPackageVariable) error {
return nil
}
-func validatePackageConstant(subject types.ZarfPackageConstant) error {
+func validatePackageConstant(subject variables.Constant) error {
// ensure the constant name is only capitals and underscores
if !IsUppercaseNumberUnderscore(subject.Name) {
return fmt.Errorf(lang.PkgValidateErrPkgConstantName, subject.Name)
diff --git a/src/pkg/interactive/prompt.go b/src/pkg/interactive/prompt.go
index 63aa058f1e..d832982538 100644
--- a/src/pkg/interactive/prompt.go
+++ b/src/pkg/interactive/prompt.go
@@ -9,7 +9,7 @@ import (
"github.com/AlecAivazis/survey/v2"
"github.com/defenseunicorns/zarf/src/pkg/message"
- "github.com/defenseunicorns/zarf/src/types"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
)
// PromptSigPassword prompts the user for the password to their private key
@@ -23,7 +23,7 @@ func PromptSigPassword() ([]byte, error) {
}
// PromptVariable prompts the user for a value for a variable
-func PromptVariable(variable types.ZarfPackageVariable) (value string, err error) {
+func PromptVariable(variable variables.InteractiveVariable) (value string, err error) {
if variable.Description != "" {
message.Question(variable.Description)
diff --git a/src/pkg/message/message.go b/src/pkg/message/message.go
index 4cc6e7fd39..1801c7b9f5 100644
--- a/src/pkg/message/message.go
+++ b/src/pkg/message/message.go
@@ -14,6 +14,7 @@ import (
"strings"
"time"
+ "github.com/defenseunicorns/pkg/helpers"
"github.com/defenseunicorns/zarf/src/config"
"github.com/fatih/color"
"github.com/pterm/pterm"
@@ -253,7 +254,7 @@ func Title(title string, help string) {
// HeaderInfof prints a large header with a formatted message.
func HeaderInfof(format string, a ...any) {
pterm.Println()
- message := Truncate(fmt.Sprintf(format, a...), TermWidth, false)
+ message := helpers.Truncate(fmt.Sprintf(format, a...), TermWidth, false)
// Ensure the text is consistent for the header width
padding := TermWidth - len(message)
pterm.DefaultHeader.
@@ -299,23 +300,6 @@ func PrintDiff(textA, textB string) {
pterm.Println(dmp.DiffPrettyText(diffs))
}
-// Truncate truncates provided text to the requested length
-func Truncate(text string, length int, invert bool) string {
- // Remove newlines and replace with semicolons
- textEscaped := strings.ReplaceAll(text, "\n", "; ")
- // Truncate the text if it is longer than length so it isn't too long.
- if len(textEscaped) > length {
- if invert {
- start := len(textEscaped) - length + 3
- textEscaped = "..." + textEscaped[start:]
- } else {
- end := length - 3
- textEscaped = textEscaped[:end] + "..."
- }
- }
- return textEscaped
-}
-
// Table prints a padded table containing the specified header and data
func Table(header []string, data [][]string) {
pterm.Println()
diff --git a/src/pkg/packager/actions/actions.go b/src/pkg/packager/actions/actions.go
index 372feeb39e..e68947895b 100644
--- a/src/pkg/packager/actions/actions.go
+++ b/src/pkg/packager/actions/actions.go
@@ -17,13 +17,18 @@ import (
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/defenseunicorns/zarf/src/pkg/utils/exec"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
)
// Run runs all provided actions.
-func Run(cfg *types.PackagerConfig, defaultCfg types.ZarfComponentActionDefaults, actions []types.ZarfComponentAction, valueTemplate *template.Values) error {
+func Run(defaultCfg types.ZarfComponentActionDefaults, actions []types.ZarfComponentAction, variableConfig *variables.VariableConfig) error {
+ if variableConfig == nil {
+ variableConfig = template.GetZarfVariableConfig()
+ }
+
for _, a := range actions {
- if err := runAction(cfg, defaultCfg, a, valueTemplate); err != nil {
+ if err := runAction(defaultCfg, a, variableConfig); err != nil {
return err
}
}
@@ -31,14 +36,13 @@ func Run(cfg *types.PackagerConfig, defaultCfg types.ZarfComponentActionDefaults
}
// Run commands that a component has provided.
-func runAction(cfg *types.PackagerConfig, defaultCfg types.ZarfComponentActionDefaults, action types.ZarfComponentAction, valueTemplate *template.Values) error {
+func runAction(defaultCfg types.ZarfComponentActionDefaults, action types.ZarfComponentAction, variableConfig *variables.VariableConfig) error {
var (
ctx context.Context
cancel context.CancelFunc
cmdEscaped string
out string
err error
- vars map[string]*template.TextTemplate
cmd = action.Cmd
)
@@ -68,27 +72,20 @@ func runAction(cfg *types.PackagerConfig, defaultCfg types.ZarfComponentActionDe
d := ""
action.Dir = &d
action.Env = []string{}
- action.SetVariables = []types.ZarfComponentActionSetVariable{}
+ action.SetVariables = []variables.Variable{}
}
if action.Description != "" {
cmdEscaped = action.Description
} else {
- cmdEscaped = message.Truncate(cmd, 60, false)
+ cmdEscaped = helpers.Truncate(cmd, 60, false)
}
spinner := message.NewProgressSpinner("Running \"%s\"", cmdEscaped)
// Persist the spinner output so it doesn't get overwritten by the command output.
spinner.EnablePreserveWrites()
- // If the value template is not nil, get the variables for the action.
- // No special variables or deprecations will be used in the action.
- // Reload the variables each time in case they have been changed by a previous action.
- if valueTemplate != nil {
- vars, _ = valueTemplate.GetVariables(types.ZarfComponent{})
- }
-
- actionDefaults := actionGetCfg(defaultCfg, action, vars)
+ actionDefaults := actionGetCfg(defaultCfg, action, variableConfig.GetAllTemplates())
if cmd, err = actionCmdMutation(cmd, actionDefaults.Shell); err != nil {
spinner.Errorf(err, "Error mutating command: %s", cmdEscaped)
@@ -112,8 +109,8 @@ retryCmd:
// If an output variable is defined, set it.
for _, v := range action.SetVariables {
- cfg.SetVariable(v.Name, out, v.Sensitive, v.AutoIndent, v.Type)
- if err := cfg.CheckVariablePattern(v.Name, v.Pattern); err != nil {
+ variableConfig.SetVariable(v.Name, out, v.Sensitive, v.AutoIndent, v.Type)
+ if err := variableConfig.CheckVariablePattern(v.Name, v.Pattern); err != nil {
message.WarnErr(err, err.Error())
return err
}
@@ -241,7 +238,7 @@ func actionCmdMutation(cmd string, shellPref exec.Shell) (string, error) {
}
// Merge the ActionSet defaults with the action config.
-func actionGetCfg(cfg types.ZarfComponentActionDefaults, a types.ZarfComponentAction, vars map[string]*template.TextTemplate) types.ZarfComponentActionDefaults {
+func actionGetCfg(cfg types.ZarfComponentActionDefaults, a types.ZarfComponentAction, vars map[string]*variables.TextTemplate) types.ZarfComponentActionDefaults {
if a.Mute != nil {
cfg.Mute = *a.Mute
}
diff --git a/src/pkg/packager/common.go b/src/pkg/packager/common.go
index ba1335852e..319874d26b 100644
--- a/src/pkg/packager/common.go
+++ b/src/pkg/packager/common.go
@@ -17,6 +17,7 @@ import (
"github.com/defenseunicorns/zarf/src/config/lang"
"github.com/defenseunicorns/zarf/src/internal/packager/template"
"github.com/defenseunicorns/zarf/src/pkg/cluster"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
"github.com/defenseunicorns/zarf/src/config"
@@ -30,10 +31,11 @@ import (
// Packager is the main struct for managing packages.
type Packager struct {
cfg *types.PackagerConfig
+ variableConfig *variables.VariableConfig
+ state *types.ZarfState
cluster *cluster.Cluster
layout *layout.PackagePaths
warnings []string
- valueTemplate *template.Values
hpaModified bool
connectStrings types.ConnectStrings
sbomViewFiles []string
@@ -77,10 +79,6 @@ func New(cfg *types.PackagerConfig, mods ...Modifier) (*Packager, error) {
return nil, fmt.Errorf("no config provided")
}
- if cfg.SetVariableMap == nil {
- cfg.SetVariableMap = make(map[string]*types.ZarfSetVariable)
- }
-
var (
err error
pkgr = &Packager{
@@ -88,6 +86,8 @@ func New(cfg *types.PackagerConfig, mods ...Modifier) (*Packager, error) {
}
)
+ pkgr.variableConfig = template.GetZarfVariableConfig()
+
if config.CommonOptions.TempDirectory != "" {
// If the cache directory is within the temp directory, warn the user
if strings.HasPrefix(config.CommonOptions.CachePath, config.CommonOptions.TempDirectory) {
diff --git a/src/pkg/packager/composer/list.go b/src/pkg/packager/composer/list.go
index 6b290203ea..dced62b0f1 100644
--- a/src/pkg/packager/composer/list.go
+++ b/src/pkg/packager/composer/list.go
@@ -15,6 +15,7 @@ import (
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/packager/deprecated"
"github.com/defenseunicorns/zarf/src/pkg/utils"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/pkg/zoci"
"github.com/defenseunicorns/zarf/src/types"
)
@@ -25,8 +26,8 @@ type Node struct {
index int
- vars []types.ZarfPackageVariable
- consts []types.ZarfPackageConstant
+ vars []variables.InteractiveVariable
+ consts []variables.Constant
relativeToHead string
originalPackageName string
@@ -95,7 +96,7 @@ func (ic *ImportChain) Tail() *Node {
}
func (ic *ImportChain) append(c types.ZarfComponent, index int, originalPackageName string,
- relativeToHead string, vars []types.ZarfPackageVariable, consts []types.ZarfPackageConstant) {
+ relativeToHead string, vars []variables.InteractiveVariable, consts []variables.Constant) {
node := &Node{
ZarfComponent: c,
index: index,
@@ -312,8 +313,8 @@ func (ic *ImportChain) Compose() (composed *types.ZarfComponent, err error) {
}
// MergeVariables merges variables from the import chain
-func (ic *ImportChain) MergeVariables(existing []types.ZarfPackageVariable) (merged []types.ZarfPackageVariable) {
- exists := func(v1 types.ZarfPackageVariable, v2 types.ZarfPackageVariable) bool {
+func (ic *ImportChain) MergeVariables(existing []variables.InteractiveVariable) (merged []variables.InteractiveVariable) {
+ exists := func(v1 variables.InteractiveVariable, v2 variables.InteractiveVariable) bool {
return v1.Name == v2.Name
}
@@ -329,8 +330,8 @@ func (ic *ImportChain) MergeVariables(existing []types.ZarfPackageVariable) (mer
}
// MergeConstants merges constants from the import chain
-func (ic *ImportChain) MergeConstants(existing []types.ZarfPackageConstant) (merged []types.ZarfPackageConstant) {
- exists := func(c1 types.ZarfPackageConstant, c2 types.ZarfPackageConstant) bool {
+func (ic *ImportChain) MergeConstants(existing []variables.Constant) (merged []variables.Constant) {
+ exists := func(c1 variables.Constant, c2 variables.Constant) bool {
return c1.Name == c2.Name
}
diff --git a/src/pkg/packager/composer/list_test.go b/src/pkg/packager/composer/list_test.go
index d80f3633c3..73e84a85fa 100644
--- a/src/pkg/packager/composer/list_test.go
+++ b/src/pkg/packager/composer/list_test.go
@@ -10,6 +10,7 @@ import (
"path/filepath"
"testing"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
"github.com/defenseunicorns/zarf/src/types/extensions"
"github.com/stretchr/testify/require"
@@ -265,23 +266,23 @@ func TestMerging(t *testing.T) {
type testCase struct {
name string
ic *ImportChain
- existingVars []types.ZarfPackageVariable
- existingConsts []types.ZarfPackageConstant
- expectedVars []types.ZarfPackageVariable
- expectedConsts []types.ZarfPackageConstant
+ existingVars []variables.InteractiveVariable
+ existingConsts []variables.Constant
+ expectedVars []variables.InteractiveVariable
+ expectedConsts []variables.Constant
}
head := Node{
- vars: []types.ZarfPackageVariable{
+ vars: []variables.InteractiveVariable{
{
- Name: "TEST",
- Default: "head",
+ Variable: variables.Variable{Name: "TEST"},
+ Default: "head",
},
{
- Name: "HEAD",
+ Variable: variables.Variable{Name: "HEAD"},
},
},
- consts: []types.ZarfPackageConstant{
+ consts: []variables.Constant{
{
Name: "TEST",
Value: "head",
@@ -292,16 +293,16 @@ func TestMerging(t *testing.T) {
},
}
tail := Node{
- vars: []types.ZarfPackageVariable{
+ vars: []variables.InteractiveVariable{
{
- Name: "TEST",
- Default: "tail",
+ Variable: variables.Variable{Name: "TEST"},
+ Default: "tail",
},
{
- Name: "TAIL",
+ Variable: variables.Variable{Name: "TAIL"},
},
},
- consts: []types.ZarfPackageConstant{
+ consts: []variables.Constant{
{
Name: "TEST",
Value: "tail",
@@ -319,22 +320,22 @@ func TestMerging(t *testing.T) {
{
name: "empty-ic",
ic: &ImportChain{},
- existingVars: []types.ZarfPackageVariable{
+ existingVars: []variables.InteractiveVariable{
{
- Name: "TEST",
+ Variable: variables.Variable{Name: "TEST"},
},
},
- existingConsts: []types.ZarfPackageConstant{
+ existingConsts: []variables.Constant{
{
Name: "TEST",
},
},
- expectedVars: []types.ZarfPackageVariable{
+ expectedVars: []variables.InteractiveVariable{
{
- Name: "TEST",
+ Variable: variables.Variable{Name: "TEST"},
},
},
- expectedConsts: []types.ZarfPackageConstant{
+ expectedConsts: []variables.Constant{
{
Name: "TEST",
},
@@ -343,21 +344,21 @@ func TestMerging(t *testing.T) {
{
name: "no-existing",
ic: testIC,
- existingVars: []types.ZarfPackageVariable{},
- existingConsts: []types.ZarfPackageConstant{},
- expectedVars: []types.ZarfPackageVariable{
+ existingVars: []variables.InteractiveVariable{},
+ existingConsts: []variables.Constant{},
+ expectedVars: []variables.InteractiveVariable{
{
- Name: "TEST",
- Default: "head",
+ Variable: variables.Variable{Name: "TEST"},
+ Default: "head",
},
{
- Name: "HEAD",
+ Variable: variables.Variable{Name: "HEAD"},
},
{
- Name: "TAIL",
+ Variable: variables.Variable{Name: "TAIL"},
},
},
- expectedConsts: []types.ZarfPackageConstant{
+ expectedConsts: []variables.Constant{
{
Name: "TEST",
Value: "head",
@@ -373,16 +374,16 @@ func TestMerging(t *testing.T) {
{
name: "with-existing",
ic: testIC,
- existingVars: []types.ZarfPackageVariable{
+ existingVars: []variables.InteractiveVariable{
{
- Name: "TEST",
- Default: "existing",
+ Variable: variables.Variable{Name: "TEST"},
+ Default: "existing",
},
{
- Name: "EXISTING",
+ Variable: variables.Variable{Name: "EXISTING"},
},
},
- existingConsts: []types.ZarfPackageConstant{
+ existingConsts: []variables.Constant{
{
Name: "TEST",
Value: "existing",
@@ -391,22 +392,22 @@ func TestMerging(t *testing.T) {
Name: "EXISTING",
},
},
- expectedVars: []types.ZarfPackageVariable{
+ expectedVars: []variables.InteractiveVariable{
{
- Name: "TEST",
- Default: "existing",
+ Variable: variables.Variable{Name: "TEST"},
+ Default: "existing",
},
{
- Name: "EXISTING",
+ Variable: variables.Variable{Name: "EXISTING"},
},
{
- Name: "HEAD",
+ Variable: variables.Variable{Name: "HEAD"},
},
{
- Name: "TAIL",
+ Variable: variables.Variable{Name: "TAIL"},
},
},
- expectedConsts: []types.ZarfPackageConstant{
+ expectedConsts: []variables.Constant{
{
Name: "TEST",
Value: "existing",
diff --git a/src/pkg/packager/create.go b/src/pkg/packager/create.go
index 9ef4523fca..b03664ae13 100755
--- a/src/pkg/packager/create.go
+++ b/src/pkg/packager/create.go
@@ -29,7 +29,7 @@ func (p *Packager) Create() (err error) {
message.Note(fmt.Sprintf("Using build directory %s", p.cfg.CreateOpts.BaseDir))
- pc := creator.NewPackageCreator(p.cfg.CreateOpts, p.cfg, cwd)
+ pc := creator.NewPackageCreator(p.cfg.CreateOpts, cwd)
if err := helpers.CreatePathAndCopy(layout.ZarfYAML, p.layout.ZarfYAML); err != nil {
return err
diff --git a/src/pkg/packager/creator/normal.go b/src/pkg/packager/creator/normal.go
index e9904852f2..9e742d6cee 100644
--- a/src/pkg/packager/creator/normal.go
+++ b/src/pkg/packager/creator/normal.go
@@ -43,9 +43,6 @@ var (
// PackageCreator provides methods for creating normal (not skeleton) Zarf packages.
type PackageCreator struct {
createOpts types.ZarfCreateOptions
-
- // TODO: (@lucasrod16) remove PackagerConfig once actions do not depend on it: https://github.com/defenseunicorns/zarf/pull/2276
- cfg *types.PackagerConfig
}
func updateRelativeDifferentialPackagePath(path string, cwd string) string {
@@ -56,9 +53,9 @@ func updateRelativeDifferentialPackagePath(path string, cwd string) string {
}
// NewPackageCreator returns a new PackageCreator.
-func NewPackageCreator(createOpts types.ZarfCreateOptions, cfg *types.PackagerConfig, cwd string) *PackageCreator {
+func NewPackageCreator(createOpts types.ZarfCreateOptions, cwd string) *PackageCreator {
createOpts.DifferentialPackagePath = updateRelativeDifferentialPackagePath(createOpts.DifferentialPackagePath, cwd)
- return &PackageCreator{createOpts, cfg}
+ return &PackageCreator{createOpts}
}
// LoadPackageDefinition loads and configures a zarf.yaml file during package create.
@@ -133,7 +130,7 @@ func (pc *PackageCreator) Assemble(dst *layout.PackagePaths, components []types.
onCreate := component.Actions.OnCreate
onFailure := func() {
- if err := actions.Run(pc.cfg, onCreate.Defaults, onCreate.OnFailure, nil); err != nil {
+ if err := actions.Run(onCreate.Defaults, onCreate.OnFailure, nil); err != nil {
message.Debugf("unable to run component failure action: %s", err.Error())
}
}
@@ -143,7 +140,7 @@ func (pc *PackageCreator) Assemble(dst *layout.PackagePaths, components []types.
return fmt.Errorf("unable to add component %q: %w", component.Name, err)
}
- if err := actions.Run(pc.cfg, onCreate.Defaults, onCreate.OnSuccess, nil); err != nil {
+ if err := actions.Run(onCreate.Defaults, onCreate.OnSuccess, nil); err != nil {
onFailure()
return fmt.Errorf("unable to run component success action: %w", err)
}
@@ -355,7 +352,7 @@ func (pc *PackageCreator) addComponent(component types.ZarfComponent, dst *layou
}
onCreate := component.Actions.OnCreate
- if err := actions.Run(pc.cfg, onCreate.Defaults, onCreate.Before, nil); err != nil {
+ if err := actions.Run(onCreate.Defaults, onCreate.Before, nil); err != nil {
return fmt.Errorf("unable to run component before action: %w", err)
}
@@ -519,7 +516,7 @@ func (pc *PackageCreator) addComponent(component types.ZarfComponent, dst *layou
spinner.Success()
}
- if err := actions.Run(pc.cfg, onCreate.Defaults, onCreate.After, nil); err != nil {
+ if err := actions.Run(onCreate.Defaults, onCreate.After, nil); err != nil {
return fmt.Errorf("unable to run component after action: %w", err)
}
diff --git a/src/pkg/packager/creator/template.go b/src/pkg/packager/creator/template.go
index 53b22ba206..df2fc86038 100644
--- a/src/pkg/packager/creator/template.go
+++ b/src/pkg/packager/creator/template.go
@@ -11,6 +11,7 @@ import (
"github.com/defenseunicorns/zarf/src/config/lang"
"github.com/defenseunicorns/zarf/src/pkg/interactive"
"github.com/defenseunicorns/zarf/src/pkg/utils"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
)
@@ -32,8 +33,8 @@ func FillActiveTemplate(pkg types.ZarfPackage, setVariables map[string]string) (
_, present := setVariables[key]
if !present && !config.CommonOptions.Confirm {
- setVal, err := interactive.PromptVariable(types.ZarfPackageVariable{
- Name: key,
+ setVal, err := interactive.PromptVariable(variables.InteractiveVariable{
+ Variable: variables.Variable{Name: key},
})
if err != nil {
return err
diff --git a/src/pkg/packager/deploy.go b/src/pkg/packager/deploy.go
index 67eccff4db..ef4495be0a 100644
--- a/src/pkg/packager/deploy.go
+++ b/src/pkg/packager/deploy.go
@@ -27,7 +27,6 @@ import (
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/packager/actions"
"github.com/defenseunicorns/zarf/src/pkg/packager/filters"
- "github.com/defenseunicorns/zarf/src/pkg/packager/variables"
"github.com/defenseunicorns/zarf/src/pkg/transform"
"github.com/defenseunicorns/zarf/src/types"
corev1 "k8s.io/api/core/v1"
@@ -64,8 +63,8 @@ func (p *Packager) Deploy() (err error) {
return fmt.Errorf("unable to load the package: %w", err)
}
- if err := variables.SetVariableMapInConfig(p.cfg); err != nil {
- return err
+ if err := p.populatePackageVariableConfig(); err != nil {
+ return fmt.Errorf("unable to set the active variables: %w", err)
}
}
@@ -93,8 +92,8 @@ func (p *Packager) Deploy() (err error) {
}
// Set variables and prompt if --confirm is not set
- if err := variables.SetVariableMapInConfig(p.cfg); err != nil {
- return err
+ if err := p.populatePackageVariableConfig(); err != nil {
+ return fmt.Errorf("unable to set the active variables: %w", err)
}
}
@@ -122,10 +121,6 @@ func (p *Packager) Deploy() (err error) {
// deployComponents loops through a list of ZarfComponents and deploys them.
func (p *Packager) deployComponents() (deployedComponents []types.DeployedComponent, err error) {
- // Generate a value template
- if p.valueTemplate, err = template.Generate(p.cfg); err != nil {
- return deployedComponents, fmt.Errorf("unable to generate the value template: %w", err)
- }
// Check if this package has been deployed before and grab relevant information about already deployed components
if p.generation == 0 {
@@ -183,7 +178,7 @@ func (p *Packager) deployComponents() (deployedComponents []types.DeployedCompon
onDeploy := component.Actions.OnDeploy
onFailure := func() {
- if err := actions.Run(p.cfg, onDeploy.Defaults, onDeploy.OnFailure, p.valueTemplate); err != nil {
+ if err := actions.Run(onDeploy.Defaults, onDeploy.OnFailure, p.variableConfig); err != nil {
message.Debugf("unable to run component failure action: %s", err.Error())
}
}
@@ -211,7 +206,7 @@ func (p *Packager) deployComponents() (deployedComponents []types.DeployedCompon
}
}
- if err := actions.Run(p.cfg, onDeploy.Defaults, onDeploy.OnSuccess, p.valueTemplate); err != nil {
+ if err := actions.Run(onDeploy.Defaults, onDeploy.OnSuccess, p.variableConfig); err != nil {
onFailure()
return deployedComponents, fmt.Errorf("unable to run component success action: %w", err)
}
@@ -233,7 +228,7 @@ func (p *Packager) deployInitComponent(component types.ZarfComponent) (charts []
}
// Always init the state before the first component that requires the cluster (on most deployments, the zarf-seed-registry)
- if component.RequiresCluster() && p.cfg.State == nil {
+ if component.RequiresCluster() && p.state == nil {
err = p.cluster.InitZarfState(p.cfg.InitOpts)
if err != nil {
return charts, fmt.Errorf("unable to initialize Zarf state: %w", err)
@@ -287,15 +282,17 @@ func (p *Packager) deployComponent(component types.ZarfComponent, noImgChecksum
onDeploy := component.Actions.OnDeploy
- if !p.valueTemplate.Ready() && component.RequiresCluster() {
- // Setup the state in the config and get the valuesTemplate
- p.valueTemplate, err = p.setupStateValuesTemplate()
- if err != nil {
- return charts, err
+ if component.RequiresCluster() {
+ // Setup the state in the config
+ if p.state == nil {
+ err = p.setupState()
+ if err != nil {
+ return charts, err
+ }
}
// Disable the registry HPA scale down if we are deploying images and it is not already disabled
- if hasImages && !p.hpaModified && p.cfg.State.RegistryInfo.InternalRegistry {
+ if hasImages && !p.hpaModified && p.state.RegistryInfo.InternalRegistry {
if err := p.cluster.DisableRegHPAScaleDown(); err != nil {
message.Debugf("unable to disable the registry HPA scale down: %s", err.Error())
} else {
@@ -304,7 +301,12 @@ func (p *Packager) deployComponent(component types.ZarfComponent, noImgChecksum
}
}
- if err = actions.Run(p.cfg, onDeploy.Defaults, onDeploy.Before, p.valueTemplate); err != nil {
+ err = p.populateComponentAndStateTemplates(component.Name)
+ if err != nil {
+ return charts, err
+ }
+
+ if err = actions.Run(onDeploy.Defaults, onDeploy.Before, p.variableConfig); err != nil {
return charts, fmt.Errorf("unable to run component before action: %w", err)
}
@@ -342,7 +344,7 @@ func (p *Packager) deployComponent(component types.ZarfComponent, noImgChecksum
}
}
- if err = actions.Run(p.cfg, onDeploy.Defaults, onDeploy.After, p.valueTemplate); err != nil {
+ if err = actions.Run(onDeploy.Defaults, onDeploy.After, p.variableConfig); err != nil {
return charts, fmt.Errorf("unable to run component after action: %w", err)
}
@@ -392,7 +394,7 @@ func (p *Packager) processComponentFiles(component types.ZarfComponent, pkgLocat
// If the file is a text file, template it
if isText {
spinner.Updatef("Templating %s", file.Target)
- if err := p.valueTemplate.Apply(component, subFile, true); err != nil {
+ if err := p.variableConfig.ReplaceTextTemplate(subFile); err != nil {
return fmt.Errorf("unable to template file %s: %w", subFile, err)
}
}
@@ -428,8 +430,8 @@ func (p *Packager) processComponentFiles(component types.ZarfComponent, pkgLocat
return nil
}
-// setupStateValuesTemplate fetched the current ZarfState from the k8s cluster and generate a p.valueTemplate from the state values.
-func (p *Packager) setupStateValuesTemplate() (values *template.Values, err error) {
+// setupState fetches the current ZarfState from the k8s cluster and sets the packager to use it
+func (p *Packager) setupState() (err error) {
// If we are touching K8s, make sure we can talk to it once per deployment
spinner := message.NewProgressSpinner("Loading the Zarf State from the Kubernetes cluster")
defer spinner.Stop()
@@ -437,7 +439,7 @@ func (p *Packager) setupStateValuesTemplate() (values *template.Values, err erro
state, err := p.cluster.LoadZarfState()
// Return on error if we are not in YOLO mode
if err != nil && !p.cfg.Pkg.Metadata.YOLO {
- return nil, fmt.Errorf("%s %w", lang.ErrLoadState, err)
+ return fmt.Errorf("%s %w", lang.ErrLoadState, err)
} else if state == nil && p.cfg.Pkg.Metadata.YOLO {
state = &types.ZarfState{}
// YOLO mode, so minimal state needed
@@ -457,16 +459,24 @@ func (p *Packager) setupStateValuesTemplate() (values *template.Values, err erro
"the pod or namespace label `zarf.dev/agent: ignore'.")
}
- p.cfg.State = state
+ p.state = state
+
+ spinner.Success()
+ return nil
+}
- // Continue loading state data if it is valid
- values, err = template.Generate(p.cfg)
+func (p *Packager) populateComponentAndStateTemplates(componentName string) error {
+ applicationTemplates, err := template.GetZarfTemplates(componentName, p.state)
if err != nil {
- return values, err
+ return err
}
+ p.variableConfig.SetApplicationTemplates(applicationTemplates)
+ return nil
+}
- spinner.Success()
- return values, nil
+func (p *Packager) populatePackageVariableConfig() error {
+ p.variableConfig.SetConstants(p.cfg.Pkg.Constants)
+ return p.variableConfig.PopulateVariables(p.cfg.Pkg.Variables, p.cfg.PkgOpts.SetVariables)
}
// Push all of the components images to the configured container registry.
@@ -490,7 +500,7 @@ func (p *Packager) pushImagesToRegistry(componentImages []string, noImgChecksum
ImagesPath: p.layout.Images.Base,
ImageList: imageList,
NoChecksum: noImgChecksum,
- RegInfo: p.cfg.State.RegistryInfo,
+ RegInfo: p.state.RegistryInfo,
Insecure: config.CommonOptions.Insecure,
Architectures: []string{p.cfg.Pkg.Build.Architecture},
}
@@ -505,7 +515,7 @@ func (p *Packager) pushReposToRepository(reposPath string, repos []string) error
for _, repoURL := range repos {
// Create an anonymous function to push the repo to the Zarf git server
tryPush := func() error {
- gitClient := git.New(p.cfg.State.GitServer)
+ gitClient := git.New(p.state.GitServer)
svcInfo, _ := k8s.ServiceInfoFromServiceURL(gitClient.Server.Address)
var err error
@@ -547,24 +557,14 @@ func (p *Packager) pushReposToRepository(reposPath string, repos []string) error
return nil
}
-// generateValuesOverrides creates a map containing overrides for chart values based on the given inputs.
-// It prioritizes the overrides in this order:
-// 1. Variables defined in the ZarfComponent, including both Set Variables and Chart Variables.
-// 2. Deployment options specified through DeployOpts.
-// This function is useful for customizing the deployment of a Helm chart by programmatically setting chart values.
-//
-// Returns:
-// - A map containing the final set of value overrides for the chart, where keys are the variable names.
-func generateValuesOverrides(chartVariables []types.ZarfChartVariable,
- setVariableMap map[string]*types.ZarfSetVariable,
- deployOpts types.ZarfDeployOptions,
- componentName, chartName string) (map[string]any, error) {
-
+// generateValuesOverrides creates a map containing overrides for chart values based on the chart and component
+// Specifically it merges DeployOpts.ValuesOverridesMap over Zarf `variables` for a given component/chart combination
+func (p *Packager) generateValuesOverrides(chart types.ZarfChart, componentName string) (map[string]any, error) {
valuesOverrides := make(map[string]any)
chartOverrides := make(map[string]any)
- for _, variable := range chartVariables {
- if setVar, ok := setVariableMap[variable.Name]; ok && setVar != nil {
+ for _, variable := range chart.Variables {
+ if setVar, ok := p.variableConfig.GetSetVariable(variable.Name); ok && setVar != nil {
// Use the variable's path as a key to ensure unique entries for variables with the same name but different paths.
if err := helpers.MergePathAndValueIntoMap(chartOverrides, variable.Path, setVar.Value); err != nil {
return nil, fmt.Errorf("unable to merge path and value into map: %w", err)
@@ -573,33 +573,36 @@ func generateValuesOverrides(chartVariables []types.ZarfChartVariable,
}
// Apply any direct overrides specified in the deployment options for this component and chart
- if componentOverrides, ok := deployOpts.ValuesOverridesMap[componentName]; ok {
- if chartSpecificOverrides, ok := componentOverrides[chartName]; ok {
+ if componentOverrides, ok := p.cfg.DeployOpts.ValuesOverridesMap[componentName]; ok {
+ if chartSpecificOverrides, ok := componentOverrides[chart.Name]; ok {
valuesOverrides = chartSpecificOverrides
}
}
// Merge chartOverrides into valuesOverrides to ensure all overrides are applied.
// This corrects the logic to ensure that chartOverrides and valuesOverrides are merged correctly.
- return helpers.MergeMapRecursive(valuesOverrides, chartOverrides), nil
+ return helpers.MergeMapRecursive(chartOverrides, valuesOverrides), nil
}
// Install all Helm charts and raw k8s manifests into the k8s cluster.
func (p *Packager) installChartAndManifests(componentPaths *layout.ComponentPaths, component types.ZarfComponent) (installedCharts []types.InstalledChart, err error) {
for _, chart := range component.Charts {
+ // Do not wait for the chart to be ready if data injections are present.
+ if len(component.DataInjections) > 0 {
+ chart.NoWait = true
+ }
+
// zarf magic for the value file
for idx := range chart.ValuesFiles {
- chartValueName := helm.StandardValuesName(componentPaths.Values, chart, idx)
- if err := p.valueTemplate.Apply(component, chartValueName, false); err != nil {
+ valueFilePath := helm.StandardValuesName(componentPaths.Values, chart, idx)
+ if err := p.variableConfig.ReplaceTextTemplate(valueFilePath); err != nil {
return installedCharts, err
}
}
- // this is to get the overrides for the chart from the commandline and
- // the chart variables set in the ZarfComponent and as well as DeployOpts set from the Library user.
- // The order of precedence is as follows:
- // 1. Set Variables and Chart Variables from the ZarfComponent
- // 2. DeployOpts
- valuesOverrides, err := generateValuesOverrides(chart.Variables, p.cfg.SetVariableMap, p.cfg.DeployOpts, component.Name, chart.Name)
+
+ // Create a Helm values overrides map from set Zarf `variables` and DeployOpts library inputs
+ // Values overrides are to be applied in order of Helm Chart Defaults -> Zarf `valuesFiles` -> Zarf `variables` -> DeployOpts overrides
+ valuesOverrides, err := p.generateValuesOverrides(chart, component.Name)
if err != nil {
return installedCharts, err
}
@@ -609,8 +612,9 @@ func (p *Packager) installChartAndManifests(componentPaths *layout.ComponentPath
componentPaths.Charts,
componentPaths.Values,
helm.WithDeployInfo(
- component,
p.cfg,
+ p.variableConfig,
+ p.state,
p.cluster,
valuesOverrides,
p.cfg.DeployOpts.Timeout,
@@ -657,8 +661,9 @@ func (p *Packager) installChartAndManifests(componentPaths *layout.ComponentPath
p.cfg.Pkg.Metadata.Name,
component.Name,
helm.WithDeployInfo(
- component,
p.cfg,
+ p.variableConfig,
+ p.state,
p.cluster,
nil,
p.cfg.DeployOpts.Timeout,
@@ -695,7 +700,7 @@ func (p *Packager) printTablesForDeployment(componentsToDeploy []types.DeployedC
// Grab a fresh copy of the state (if we are able) to print the most up-to-date version of the creds
freshState, err := p.cluster.LoadZarfState()
if err != nil {
- freshState = p.cfg.State
+ freshState = p.state
}
// otherwise, print the init config connection and passwords
message.PrintCredentialTable(freshState, componentsToDeploy)
diff --git a/src/pkg/packager/deploy_test.go b/src/pkg/packager/deploy_test.go
index 2b235b9c56..d79f19f1a5 100644
--- a/src/pkg/packager/deploy_test.go
+++ b/src/pkg/packager/deploy_test.go
@@ -7,6 +7,8 @@ import (
"reflect"
"testing"
+ "github.com/defenseunicorns/zarf/src/pkg/packager/sources"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
)
@@ -14,52 +16,54 @@ func TestGenerateValuesOverrides(t *testing.T) {
t.Parallel()
tests := []struct {
- name string
- chartVariables []types.ZarfChartVariable
- setVariableMap map[string]*types.ZarfSetVariable
- deployOpts types.ZarfDeployOptions
- componentName string
- chartName string
- want map[string]any
+ name string
+ chart types.ZarfChart
+ setVariables map[string]string
+ deployOpts types.ZarfDeployOptions
+ componentName string
+ want map[string]any
}{
{
- name: "Empty inputs",
- chartVariables: []types.ZarfChartVariable{},
- setVariableMap: map[string]*types.ZarfSetVariable{},
- deployOpts: types.ZarfDeployOptions{},
- componentName: "",
- chartName: "",
- want: map[string]any{},
+ name: "Empty inputs",
+ chart: types.ZarfChart{},
+ setVariables: map[string]string{},
+ deployOpts: types.ZarfDeployOptions{},
+ componentName: "",
+ want: map[string]any{},
},
{
- name: "Single variable",
- chartVariables: []types.ZarfChartVariable{{Name: "testVar", Path: "testVar"}},
- setVariableMap: map[string]*types.ZarfSetVariable{"testVar": {Value: "testValue"}},
- deployOpts: types.ZarfDeployOptions{},
- componentName: "testComponent",
- chartName: "testChart",
- want: map[string]any{"testVar": "testValue"},
+ name: "Single variable",
+ chart: types.ZarfChart{
+ Name: "test-chart",
+ Variables: []types.ZarfChartVariable{{Name: "TEST_VAR", Path: "testVar"}},
+ },
+ setVariables: map[string]string{"TEST_VAR": "testValue"},
+ deployOpts: types.ZarfDeployOptions{},
+ componentName: "test-component",
+ want: map[string]any{"testVar": "testValue"},
},
{
- name: "Non-matching setVariable",
- chartVariables: []types.ZarfChartVariable{{Name: "expectedVar", Path: "path.to.expectedVar"}},
- setVariableMap: map[string]*types.ZarfSetVariable{"unexpectedVar": {Value: "unexpectedValue"}},
- deployOpts: types.ZarfDeployOptions{},
- componentName: "testComponent",
- chartName: "testChart",
- want: map[string]any{},
+ name: "Non-matching setVariable",
+ chart: types.ZarfChart{
+ Name: "test-chart",
+ Variables: []types.ZarfChartVariable{{Name: "EXPECTED_VAR", Path: "path.to.expectedVar"}},
+ },
+ setVariables: map[string]string{"UNEXPECTED_VAR": "unexpectedValue"},
+ deployOpts: types.ZarfDeployOptions{},
+ componentName: "test-component",
+ want: map[string]any{},
},
{
- name: "Nested 3 level setVariableMap",
- chartVariables: []types.ZarfChartVariable{
- {Name: "level1.level2.level3Var", Path: "level1.level2.level3Var"},
- },
- setVariableMap: map[string]*types.ZarfSetVariable{
- "level1.level2.level3Var": {Value: "nestedValue"},
+ name: "Nested 3 level setVariables",
+ chart: types.ZarfChart{
+ Name: "nested-chart",
+ Variables: []types.ZarfChartVariable{
+ {Name: "LEVEL1_LEVEL2_LEVEL3_VAR", Path: "level1.level2.level3Var"},
+ },
},
+ setVariables: map[string]string{"LEVEL1_LEVEL2_LEVEL3_VAR": "nestedValue"},
deployOpts: types.ZarfDeployOptions{},
- componentName: "nestedComponent",
- chartName: "nestedChart",
+ componentName: "nested-component",
want: map[string]any{
"level1": map[string]any{
"level2": map[string]any{
@@ -70,17 +74,19 @@ func TestGenerateValuesOverrides(t *testing.T) {
},
{
name: "Multiple variables with nested and non-nested paths, distinct values",
- chartVariables: []types.ZarfChartVariable{
- {Name: "NESTED_VAR_LEVEL2", Path: "nestedVar.level2"},
- {Name: "simpleVar", Path: "simpleVar"},
+ chart: types.ZarfChart{
+ Name: "mixed-chart",
+ Variables: []types.ZarfChartVariable{
+ {Name: "NESTED_VAR_LEVEL2", Path: "nestedVar.level2"},
+ {Name: "SIMPLE_VAR", Path: "simpleVar"},
+ },
},
- setVariableMap: map[string]*types.ZarfSetVariable{
- "NESTED_VAR_LEVEL2": {Value: "distinctNestedValue"},
- "simpleVar": {Value: "distinctSimpleValue"},
+ setVariables: map[string]string{
+ "NESTED_VAR_LEVEL2": "distinctNestedValue",
+ "SIMPLE_VAR": "distinctSimpleValue",
},
deployOpts: types.ZarfDeployOptions{},
- componentName: "mixedComponent",
- chartName: "mixedChart",
+ componentName: "mixed-component",
want: map[string]any{
"nestedVar": map[string]any{
"level2": "distinctNestedValue",
@@ -90,93 +96,94 @@ func TestGenerateValuesOverrides(t *testing.T) {
},
{
name: "Values override test",
- chartVariables: []types.ZarfChartVariable{
- {Name: "overrideVar", Path: "path"},
- },
- setVariableMap: map[string]*types.ZarfSetVariable{
- "path": {Value: "overrideValue"},
+ chart: types.ZarfChart{
+ Name: "test-chart",
+ Variables: []types.ZarfChartVariable{
+ {Name: "OVERRIDE_VAR", Path: "path"},
+ },
},
+ setVariables: map[string]string{"OVERRIDE_VAR": "overrideValue"},
deployOpts: types.ZarfDeployOptions{
ValuesOverridesMap: map[string]map[string]map[string]any{
- "testComponent": {
- "testChart": {
+ "test-component": {
+ "test-chart": {
"path": "deployOverrideValue",
},
},
},
},
- componentName: "testComponent",
- chartName: "testChart",
+ componentName: "test-component",
want: map[string]any{
"path": "deployOverrideValue",
},
},
{
- name: "Missing variable in setVariableMap but present in ValuesOverridesMap",
- chartVariables: []types.ZarfChartVariable{
- {Name: "missingVar", Path: "missingVarPath"},
+ name: "Missing variable in setVariables but present in ValuesOverridesMap",
+ chart: types.ZarfChart{
+ Name: "test-chart",
+ Variables: []types.ZarfChartVariable{
+ {Name: "MISSING_VAR", Path: "missingVarPath"},
+ },
},
- setVariableMap: map[string]*types.ZarfSetVariable{},
+ setVariables: map[string]string{},
deployOpts: types.ZarfDeployOptions{
ValuesOverridesMap: map[string]map[string]map[string]any{
- "testComponent": {
- "testChart": {
+ "test-component": {
+ "test-chart": {
"missingVarPath": "overrideValue",
},
},
},
},
- componentName: "testComponent",
- chartName: "testChart",
+ componentName: "test-component",
want: map[string]any{
"missingVarPath": "overrideValue",
},
},
{
- name: "Non-existent component or chart",
- chartVariables: []types.ZarfChartVariable{{Name: "someVar", Path: "someVar"}},
- setVariableMap: map[string]*types.ZarfSetVariable{"someVar": {Value: "value"}},
+ name: "Non-existent component or chart",
+ chart: types.ZarfChart{
+ Name: "actual-chart",
+ Variables: []types.ZarfChartVariable{{Name: "SOME_VAR", Path: "someVar"}},
+ },
+ setVariables: map[string]string{"SOME_VAR": "value"},
deployOpts: types.ZarfDeployOptions{
ValuesOverridesMap: map[string]map[string]map[string]any{
- "nonExistentComponent": {
- "nonExistentChart": {
+ "non-existent-component": {
+ "non-existent-chart": {
"someVar": "overrideValue",
},
},
},
},
- componentName: "actualComponent",
- chartName: "actualChart",
+ componentName: "actual-component",
want: map[string]any{"someVar": "value"},
},
{
- name: "Variable in setVariableMap but not in chartVariables",
- chartVariables: []types.ZarfChartVariable{},
- setVariableMap: map[string]*types.ZarfSetVariable{
- "orphanVar": {Value: "orphanValue"},
- },
+ name: "Variable in setVariables but not in chartVariables",
+ chart: types.ZarfChart{Name: "orphan-chart"},
+ setVariables: map[string]string{"ORPHAN_VAR": "orphanValue"},
deployOpts: types.ZarfDeployOptions{},
- componentName: "orphanComponent",
- chartName: "orphanChart",
+ componentName: "orphan-component",
want: map[string]any{},
},
{
name: "Empty ValuesOverridesMap with non-empty setVariableMap and chartVariables",
- chartVariables: []types.ZarfChartVariable{
- {Name: "var1", Path: "path.to.var1"},
- {Name: "var2", Path: "path.to.var2"},
- {Name: "var3", Path: "path.to3.var3"},
- },
- setVariableMap: map[string]*types.ZarfSetVariable{
- "var1": {Value: "value1"},
- "var2": {Value: "value2"},
- "var3": {Value: "value3"},
+ chart: types.ZarfChart{
+ Name: "chart-with-vars",
+ Variables: []types.ZarfChartVariable{
+ {Name: "VAR1", Path: "path.to.var1"},
+ {Name: "VAR2", Path: "path.to.var2"},
+ {Name: "VAR3", Path: "path.to3.var3"},
+ },
},
- deployOpts: types.ZarfDeployOptions{
- ValuesOverridesMap: map[string]map[string]map[string]any{},
+ setVariables: map[string]string{
+ "VAR1": "value1",
+ "VAR2": "value2",
+ "VAR3": "value3",
},
- componentName: "componentWithVars",
- chartName: "chartWithVars",
+ deployOpts: types.ZarfDeployOptions{},
+ componentName: "component-with-vars",
want: map[string]any{
"path": map[string]any{
"to": map[string]any{
@@ -190,15 +197,14 @@ func TestGenerateValuesOverrides(t *testing.T) {
},
},
{
- name: "Empty chartVariables and non-empty setVariableMap",
- chartVariables: []types.ZarfChartVariable{},
- setVariableMap: map[string]*types.ZarfSetVariable{
- "var1": {Value: "value1"},
- "var2": {Value: "value2"},
+ name: "Empty chartVariables and non-empty setVariableMap",
+ chart: types.ZarfChart{Name: "chart-with-vars"},
+ setVariables: map[string]string{
+ "VAR1": "value1",
+ "VAR2": "value2",
},
deployOpts: types.ZarfDeployOptions{},
- componentName: "componentWithVars",
- chartName: "chartWithVars",
+ componentName: "component-with-vars",
want: map[string]any{},
},
}
@@ -206,7 +212,12 @@ func TestGenerateValuesOverrides(t *testing.T) {
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
- got, err := generateValuesOverrides(tt.chartVariables, tt.setVariableMap, tt.deployOpts, tt.componentName, tt.chartName)
+ p := NewOrDie(&types.PackagerConfig{DeployOpts: tt.deployOpts}, WithSource(&sources.TarballSource{}))
+ for k, v := range tt.setVariables {
+ p.variableConfig.SetVariable(k, v, false, false, variables.RawVariableType)
+ }
+
+ got, err := p.generateValuesOverrides(tt.chart, tt.componentName)
if err != nil {
t.Errorf("%s: generateValuesOverrides() error = %v", tt.name, err)
}
diff --git a/src/pkg/packager/deprecated/pluralize-set-variable.go b/src/pkg/packager/deprecated/pluralize-set-variable.go
index 9835c80a64..c3dc13e06c 100644
--- a/src/pkg/packager/deprecated/pluralize-set-variable.go
+++ b/src/pkg/packager/deprecated/pluralize-set-variable.go
@@ -7,6 +7,7 @@ package deprecated
import (
"fmt"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types"
)
@@ -17,7 +18,7 @@ func migrateSetVariableToSetVariables(c types.ZarfComponent) (types.ZarfComponen
for i := range actions {
if actions[i].DeprecatedSetVariable != "" && len(actions[i].SetVariables) < 1 {
hasSetVariable = true
- actions[i].SetVariables = []types.ZarfComponentActionSetVariable{
+ actions[i].SetVariables = []variables.Variable{
{
Name: actions[i].DeprecatedSetVariable,
Sensitive: false,
diff --git a/src/pkg/packager/dev.go b/src/pkg/packager/dev.go
index 1679933cfe..454d62f6cc 100644
--- a/src/pkg/packager/dev.go
+++ b/src/pkg/packager/dev.go
@@ -16,7 +16,6 @@ import (
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/packager/creator"
"github.com/defenseunicorns/zarf/src/pkg/packager/filters"
- "github.com/defenseunicorns/zarf/src/pkg/packager/variables"
"github.com/defenseunicorns/zarf/src/types"
)
@@ -34,7 +33,7 @@ func (p *Packager) DevDeploy() error {
return fmt.Errorf("unable to access directory %q: %w", p.cfg.CreateOpts.BaseDir, err)
}
- pc := creator.NewPackageCreator(p.cfg.CreateOpts, p.cfg, cwd)
+ pc := creator.NewPackageCreator(p.cfg.CreateOpts, cwd)
if err := helpers.CreatePathAndCopy(layout.ZarfYAML, p.layout.ZarfYAML); err != nil {
return err
@@ -58,8 +57,8 @@ func (p *Packager) DevDeploy() error {
return fmt.Errorf("unable to validate package: %w", err)
}
- if err := variables.SetVariableMapInConfig(p.cfg); err != nil {
- return err
+ if err := p.populatePackageVariableConfig(); err != nil {
+ return fmt.Errorf("unable to set the active variables: %w", err)
}
// If building in yolo mode, strip out all images and repos
diff --git a/src/pkg/packager/interactive.go b/src/pkg/packager/interactive.go
index c033f6308f..d1c0711dc7 100644
--- a/src/pkg/packager/interactive.go
+++ b/src/pkg/packager/interactive.go
@@ -10,6 +10,7 @@ import (
"path/filepath"
"github.com/AlecAivazis/survey/v2"
+ "github.com/defenseunicorns/pkg/helpers"
"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/message"
@@ -92,9 +93,9 @@ func (p *Packager) getPackageYAMLHints(stage string) map[string]string {
for _, variable := range p.cfg.Pkg.Variables {
value, present := p.cfg.PkgOpts.SetVariables[variable.Name]
if !present {
- value = fmt.Sprintf("'%s' (default)", message.Truncate(variable.Default, 20, false))
+ value = fmt.Sprintf("'%s' (default)", helpers.Truncate(variable.Default, 20, false))
} else {
- value = fmt.Sprintf("'%s'", message.Truncate(value, 20, false))
+ value = fmt.Sprintf("'%s'", helpers.Truncate(value, 20, false))
}
if variable.Sensitive {
value = "'**sanitized**'"
diff --git a/src/pkg/packager/mirror.go b/src/pkg/packager/mirror.go
index f8f90fad55..0afec2e480 100644
--- a/src/pkg/packager/mirror.go
+++ b/src/pkg/packager/mirror.go
@@ -40,7 +40,7 @@ func (p *Packager) Mirror() (err error) {
return fmt.Errorf("mirror cancelled")
}
- p.cfg.State = &types.ZarfState{
+ p.state = &types.ZarfState{
RegistryInfo: p.cfg.InitOpts.RegistryInfo,
GitServer: p.cfg.InitOpts.GitServer,
}
diff --git a/src/pkg/packager/prepare.go b/src/pkg/packager/prepare.go
index 407ddcac4c..6f5cbf0432 100644
--- a/src/pkg/packager/prepare.go
+++ b/src/pkg/packager/prepare.go
@@ -19,11 +19,9 @@ import (
"github.com/defenseunicorns/zarf/src/config/lang"
"github.com/defenseunicorns/zarf/src/internal/packager/helm"
"github.com/defenseunicorns/zarf/src/internal/packager/kustomize"
- "github.com/defenseunicorns/zarf/src/internal/packager/template"
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/packager/creator"
- "github.com/defenseunicorns/zarf/src/pkg/packager/variables"
"github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/defenseunicorns/zarf/src/types"
"github.com/google/go-containerregistry/pkg/crane"
@@ -55,7 +53,7 @@ func (p *Packager) FindImages() (imgMap map[string][]string, err error) {
}
message.Note(fmt.Sprintf("Using build directory %s", p.cfg.CreateOpts.BaseDir))
- c := creator.NewPackageCreator(p.cfg.CreateOpts, p.cfg, cwd)
+ c := creator.NewPackageCreator(p.cfg.CreateOpts, cwd)
if err := helpers.CreatePathAndCopy(layout.ZarfYAML, p.layout.ZarfYAML); err != nil {
return nil, err
@@ -94,11 +92,31 @@ func (p *Packager) findImages() (imgMap map[string][]string, err error) {
componentDefinition := "\ncomponents:\n"
- if err := variables.SetVariableMapInConfig(p.cfg); err != nil {
+ if err := p.populatePackageVariableConfig(); err != nil {
+ return nil, fmt.Errorf("unable to set the active variables: %w", err)
+ }
+
+ // Set default builtin values so they exist in case any helm charts rely on them
+ registryInfo := types.RegistryInfo{Address: p.cfg.FindImagesOpts.RegistryURL}
+ err = registryInfo.FillInEmptyValues()
+ if err != nil {
return nil, err
}
+ gitServer := types.GitServerInfo{}
+ err = gitServer.FillInEmptyValues()
+ if err != nil {
+ return nil, err
+ }
+ artifactServer := types.ArtifactServerInfo{}
+ artifactServer.FillInEmptyValues()
+ p.state = &types.ZarfState{
+ RegistryInfo: registryInfo,
+ GitServer: gitServer,
+ ArtifactServer: artifactServer,
+ }
for _, component := range p.cfg.Pkg.Components {
+
if len(component.Charts)+len(component.Manifests)+len(component.Repos) < 1 {
// Skip if it doesn't have what we need
continue
@@ -137,27 +155,11 @@ func (p *Packager) findImages() (imgMap map[string][]string, err error) {
if err != nil {
return nil, err
}
- values, err := template.Generate(p.cfg)
- if err != nil {
- return nil, fmt.Errorf("unable to generate template values")
- }
- // Adding these so the default builtin values exist in case any helm charts rely on them
- registryInfo := types.RegistryInfo{Address: p.cfg.FindImagesOpts.RegistryURL}
- err = registryInfo.FillInEmptyValues()
+ err = p.populateComponentAndStateTemplates(component.Name)
if err != nil {
return nil, err
}
- gitServer := types.GitServerInfo{}
- err = gitServer.FillInEmptyValues()
- if err != nil {
- return nil, err
- }
- artifactServer := types.ArtifactServerInfo{}
- artifactServer.FillInEmptyValues()
- values.SetState(&types.ZarfState{
- RegistryInfo: registryInfo,
- GitServer: gitServer,
- ArtifactServer: artifactServer})
+
for _, chart := range component.Charts {
helmCfg := helm.New(
@@ -165,7 +167,7 @@ func (p *Packager) findImages() (imgMap map[string][]string, err error) {
componentPaths.Charts,
componentPaths.Values,
helm.WithKubeVersion(kubeVersionOverride),
- helm.WithPackageConfig(p.cfg),
+ helm.WithVariableConfig(p.variableConfig),
)
err = helmCfg.PackageChart(component.DeprecatedCosignKeyPath)
@@ -174,8 +176,8 @@ func (p *Packager) findImages() (imgMap map[string][]string, err error) {
}
valuesFilePaths, _ := helpers.RecursiveFileList(componentPaths.Values, nil, false)
- for _, path := range valuesFilePaths {
- if err := values.Apply(component, path, false); err != nil {
+ for _, valueFilePath := range valuesFilePaths {
+ if err := p.variableConfig.ReplaceTextTemplate(valueFilePath); err != nil {
return nil, err
}
}
@@ -242,7 +244,7 @@ func (p *Packager) findImages() (imgMap map[string][]string, err error) {
f = newDestination
}
- if err := values.Apply(component, f, true); err != nil {
+ if err := p.variableConfig.ReplaceTextTemplate(f); err != nil {
return nil, err
}
// Read the contents of each file
diff --git a/src/pkg/packager/remove.go b/src/pkg/packager/remove.go
index 122e811b10..c0329ce55d 100644
--- a/src/pkg/packager/remove.go
+++ b/src/pkg/packager/remove.go
@@ -131,12 +131,12 @@ func (p *Packager) removeComponent(deployedPackage *types.DeployedPackage, deplo
onRemove := c.Actions.OnRemove
onFailure := func() {
- if err := actions.Run(p.cfg, onRemove.Defaults, onRemove.OnFailure, nil); err != nil {
+ if err := actions.Run(onRemove.Defaults, onRemove.OnFailure, nil); err != nil {
message.Debugf("Unable to run the failure action: %s", err)
}
}
- if err := actions.Run(p.cfg, onRemove.Defaults, onRemove.Before, nil); err != nil {
+ if err := actions.Run(onRemove.Defaults, onRemove.Before, nil); err != nil {
onFailure()
return nil, fmt.Errorf("unable to run the before action for component (%s): %w", c.Name, err)
}
@@ -144,7 +144,7 @@ func (p *Packager) removeComponent(deployedPackage *types.DeployedPackage, deplo
for _, chart := range helpers.Reverse(deployedComponent.InstalledCharts) {
spinner.Updatef("Uninstalling chart '%s' from the '%s' component", chart.ChartName, deployedComponent.Name)
- helmCfg := helm.NewClusterOnly(p.cfg, p.cluster)
+ helmCfg := helm.NewClusterOnly(p.cfg, p.variableConfig, p.state, p.cluster)
if err := helmCfg.RemoveChart(chart.Namespace, chart.ChartName, spinner); err != nil {
if !errors.Is(err, driver.ErrReleaseNotFound) {
onFailure()
@@ -165,12 +165,12 @@ func (p *Packager) removeComponent(deployedPackage *types.DeployedPackage, deplo
p.updatePackageSecret(*deployedPackage)
}
- if err := actions.Run(p.cfg, onRemove.Defaults, onRemove.After, nil); err != nil {
+ if err := actions.Run(onRemove.Defaults, onRemove.After, nil); err != nil {
onFailure()
return deployedPackage, fmt.Errorf("unable to run the after action: %w", err)
}
- if err := actions.Run(p.cfg, onRemove.Defaults, onRemove.OnSuccess, nil); err != nil {
+ if err := actions.Run(onRemove.Defaults, onRemove.OnSuccess, nil); err != nil {
onFailure()
return deployedPackage, fmt.Errorf("unable to run the success action: %w", err)
}
diff --git a/src/pkg/packager/variables/variables.go b/src/pkg/packager/variables/variables.go
deleted file mode 100644
index a2ab07a2e3..0000000000
--- a/src/pkg/packager/variables/variables.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-FileCopyrightText: 2021-Present The Zarf Authors
-
-// Package variables contains functions for working with variables within Zarf packages.
-package variables
-
-import (
- "github.com/defenseunicorns/zarf/src/config"
- "github.com/defenseunicorns/zarf/src/pkg/interactive"
- "github.com/defenseunicorns/zarf/src/types"
-)
-
-// SetVariableMapInConfig handles setting the active variables used to template component files.
-func SetVariableMapInConfig(cfg *types.PackagerConfig) error {
- for name, value := range cfg.PkgOpts.SetVariables {
- cfg.SetVariable(name, value, false, false, "")
- }
-
- for _, variable := range cfg.Pkg.Variables {
- _, present := cfg.SetVariableMap[variable.Name]
-
- // Variable is present, no need to continue checking
- if present {
- cfg.SetVariableMap[variable.Name].Sensitive = variable.Sensitive
- cfg.SetVariableMap[variable.Name].AutoIndent = variable.AutoIndent
- cfg.SetVariableMap[variable.Name].Type = variable.Type
- if err := cfg.CheckVariablePattern(variable.Name, variable.Pattern); err != nil {
- return err
- }
- continue
- }
-
- // First set default (may be overridden by prompt)
- cfg.SetVariable(variable.Name, variable.Default, variable.Sensitive, variable.AutoIndent, variable.Type)
-
- // Variable is set to prompt the user
- if variable.Prompt && !config.CommonOptions.Confirm {
- // Prompt the user for the variable
- val, err := interactive.PromptVariable(variable)
-
- if err != nil {
- return err
- }
-
- cfg.SetVariable(variable.Name, val, variable.Sensitive, variable.AutoIndent, variable.Type)
- }
-
- if err := cfg.CheckVariablePattern(variable.Name, variable.Pattern); err != nil {
- return err
- }
- }
-
- return nil
-}
diff --git a/src/pkg/variables/common.go b/src/pkg/variables/common.go
new file mode 100644
index 0000000000..6cf73824d1
--- /dev/null
+++ b/src/pkg/variables/common.go
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2021-Present The Zarf Authors
+
+// Package variables contains functions for interacting with variables
+package variables
+
+import (
+ "log/slog"
+)
+
+// VariableConfig represents a value to be templated into a text file.
+type VariableConfig struct {
+ templatePrefix string
+ deprecatedKeys map[string]string
+
+ applicationTemplates map[string]*TextTemplate
+ setVariableMap SetVariableMap
+ constants []Constant
+
+ prompt func(variable InteractiveVariable) (value string, err error)
+ logger *slog.Logger
+}
+
+// New creates a new VariableConfig
+func New(templatePrefix string, deprecatedKeys map[string]string, prompt func(variable InteractiveVariable) (value string, err error), logger *slog.Logger) *VariableConfig {
+ return &VariableConfig{
+ templatePrefix: templatePrefix,
+ deprecatedKeys: deprecatedKeys,
+ applicationTemplates: make(map[string]*TextTemplate),
+ setVariableMap: make(SetVariableMap),
+ prompt: prompt,
+ logger: logger,
+ }
+}
+
+// SetApplicationTemplates sets the application-specific templates for the variable config (i.e. ZARF_REGISTRY for Zarf)
+func (vc *VariableConfig) SetApplicationTemplates(applicationTemplates map[string]*TextTemplate) {
+ vc.applicationTemplates = applicationTemplates
+}
+
+// SetConstants sets the constants for a variable config (templated as PREFIX_CONST_NAME)
+func (vc *VariableConfig) SetConstants(constants []Constant) {
+ vc.constants = constants
+}
diff --git a/src/pkg/variables/templates.go b/src/pkg/variables/templates.go
new file mode 100644
index 0000000000..356345af38
--- /dev/null
+++ b/src/pkg/variables/templates.go
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2021-Present The Zarf Authors
+
+// Package variables contains functions for interacting with variables
+package variables
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "regexp"
+ "strings"
+
+ "github.com/defenseunicorns/pkg/helpers"
+)
+
+// TextTemplate represents a value to be templated into a text file.
+type TextTemplate struct {
+ Sensitive bool
+ AutoIndent bool
+ Type VariableType
+ Value string
+}
+
+// GetAllTemplates gets all of the current templates stored in the VariableConfig
+func (vc *VariableConfig) GetAllTemplates() map[string]*TextTemplate {
+ templateMap := vc.applicationTemplates
+
+ for key, variable := range vc.setVariableMap {
+ // Variable keys are always uppercase in the format ###ZARF_VAR_KEY###
+ templateMap[strings.ToUpper(fmt.Sprintf("###%s_VAR_%s###", vc.templatePrefix, key))] = &TextTemplate{
+ Value: variable.Value,
+ Sensitive: variable.Sensitive,
+ AutoIndent: variable.AutoIndent,
+ Type: variable.Type,
+ }
+ }
+
+ for _, constant := range vc.constants {
+ // Constant keys are always uppercase in the format ###ZARF_CONST_KEY###
+ templateMap[strings.ToUpper(fmt.Sprintf("###%s_CONST_%s###", vc.templatePrefix, constant.Name))] = &TextTemplate{
+ Value: constant.Value,
+ AutoIndent: constant.AutoIndent,
+ }
+ }
+
+ return templateMap
+}
+
+// ReplaceTextTemplate loads a file from a given path, replaces text in it and writes it back in place.
+func (vc *VariableConfig) ReplaceTextTemplate(path string) error {
+ templateRegex := fmt.Sprintf("###%s_[A-Z0-9_]+###", strings.ToUpper(vc.templatePrefix))
+ templateMap := vc.GetAllTemplates()
+
+ textFile, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer textFile.Close()
+
+ // This regex takes a line and parses the text before and after a discovered template: https://regex101.com/r/ilUxAz/1
+ regexTemplateLine := regexp.MustCompile(fmt.Sprintf("(?P.*?)(?P%s)(?P.*)", templateRegex))
+
+ fileScanner := bufio.NewScanner(textFile)
+
+ // Set the buffer to 1 MiB to handle long lines (i.e. base64 text in a secret)
+ // 1 MiB is around the documented maximum size for secrets and configmaps
+ const maxCapacity = 1024 * 1024
+ buf := make([]byte, maxCapacity)
+ fileScanner.Buffer(buf, maxCapacity)
+
+ // Set the scanner to split on new lines
+ fileScanner.Split(bufio.ScanLines)
+
+ text := ""
+
+ for fileScanner.Scan() {
+ line := fileScanner.Text()
+
+ for {
+ matches := regexTemplateLine.FindStringSubmatch(line)
+
+ // No template left on this line so move on
+ if len(matches) == 0 {
+ text += fmt.Sprintln(line)
+ break
+ }
+
+ preTemplate := matches[regexTemplateLine.SubexpIndex("preTemplate")]
+ templateKey := matches[regexTemplateLine.SubexpIndex("template")]
+
+ _, present := vc.deprecatedKeys[templateKey]
+ if present {
+ deprecationWarning := fmt.Sprintf("This Zarf Package uses a deprecated variable: '%s' changed to '%s'. Please notify your package creator for an update.", templateKey, vc.deprecatedKeys[templateKey])
+ vc.logger.Warn(deprecationWarning)
+ }
+
+ template := templateMap[templateKey]
+
+ // Check if the template is nil (present), use the original templateKey if not (so that it is not replaced).
+ value := templateKey
+ if template != nil {
+ value = template.Value
+
+ // Check if the value is a file type and load the value contents from the file
+ if template.Type == FileVariableType && value != "" {
+ if isText, err := helpers.IsTextFile(value); err != nil || !isText {
+ nonTextWarning := fmt.Sprintf("Refusing to load a non-text file for templating %s", templateKey)
+ vc.logger.Warn(nonTextWarning)
+ line = matches[regexTemplateLine.SubexpIndex("postTemplate")]
+ continue
+ }
+
+ contents, err := os.ReadFile(value)
+ if err != nil {
+ unableToReadWarning := fmt.Sprintf("Unable to read file for templating - skipping: %s", err.Error())
+ vc.logger.Warn(unableToReadWarning)
+ line = matches[regexTemplateLine.SubexpIndex("postTemplate")]
+ continue
+ }
+
+ value = string(contents)
+ }
+
+ // Check if the value is autoIndented and add the correct spacing
+ if template.AutoIndent {
+ indent := fmt.Sprintf("\n%s", strings.Repeat(" ", len(preTemplate)))
+ value = strings.ReplaceAll(value, "\n", indent)
+ }
+ }
+
+ // Add the processed text and continue processing the line
+ text += fmt.Sprintf("%s%s", preTemplate, value)
+ line = matches[regexTemplateLine.SubexpIndex("postTemplate")]
+ }
+ }
+
+ return os.WriteFile(path, []byte(text), helpers.ReadWriteUser)
+}
diff --git a/src/pkg/variables/types.go b/src/pkg/variables/types.go
new file mode 100644
index 0000000000..5b56fe3eeb
--- /dev/null
+++ b/src/pkg/variables/types.go
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2021-Present The Zarf Authors
+
+// Package variables contains functions for interacting with variables
+package variables
+
+// VariableType represents a type of a Zarf package variable
+type VariableType string
+
+const (
+ // RawVariableType is the default type for a Zarf package variable
+ RawVariableType VariableType = "raw"
+ // FileVariableType is a type for a Zarf package variable that loads its contents from a file
+ FileVariableType VariableType = "file"
+)
+
+// Variable represents a variable that has a value set programmatically
+type Variable struct {
+ Name string `json:"name" jsonschema:"description=The name to be used for the variable,pattern=^[A-Z0-9_]+$"`
+ Sensitive bool `json:"sensitive,omitempty" jsonschema:"description=Whether to mark this variable as sensitive to not print it in the log"`
+ AutoIndent bool `json:"autoIndent,omitempty" jsonschema:"description=Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_."`
+ Pattern string `json:"pattern,omitempty" jsonschema:"description=An optional regex pattern that a variable value must match before a package deployment can continue."`
+ Type VariableType `json:"type,omitempty" jsonschema:"description=Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB),enum=raw,enum=file"`
+}
+
+// InteractiveVariable is a variable that can be used to prompt a user for more information
+type InteractiveVariable struct {
+ Variable `json:",inline"`
+ Description string `json:"description,omitempty" jsonschema:"description=A description of the variable to be used when prompting the user a value"`
+ Default string `json:"default,omitempty" jsonschema:"description=The default value to use for the variable"`
+ Prompt bool `json:"prompt,omitempty" jsonschema:"description=Whether to prompt the user for input for this variable"`
+}
+
+// Constant are constants that can be used to dynamically template K8s resources or run in actions.
+type Constant struct {
+ Name string `json:"name" jsonschema:"description=The name to be used for the constant,pattern=^[A-Z0-9_]+$"`
+ Value string `json:"value" jsonschema:"description=The value to set for the constant during deploy"`
+ // Include a description that will only be displayed during package create/deploy confirm prompts
+ Description string `json:"description,omitempty" jsonschema:"description=A description of the constant to explain its purpose on package create or deploy confirmation prompts"`
+ AutoIndent bool `json:"autoIndent,omitempty" jsonschema:"description=Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_CONST_."`
+ Pattern string `json:"pattern,omitempty" jsonschema:"description=An optional regex pattern that a constant value must match before a package can be created."`
+}
+
+// SetVariable tracks internal variables that have been set during this run of Zarf
+type SetVariable struct {
+ Variable `json:",inline"`
+ Value string `json:"value" jsonschema:"description=The value the variable is currently set with"`
+}
diff --git a/src/pkg/variables/variables.go b/src/pkg/variables/variables.go
new file mode 100644
index 0000000000..cdd3bc4c94
--- /dev/null
+++ b/src/pkg/variables/variables.go
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2021-Present The Zarf Authors
+
+// Package variables contains functions for interacting with variables
+package variables
+
+import (
+ "fmt"
+ "regexp"
+)
+
+// SetVariableMap represents a map of variable names to their set values
+type SetVariableMap map[string]*SetVariable
+
+// GetSetVariable gets a variable set within a VariableConfig by its name
+func (vc *VariableConfig) GetSetVariable(name string) (variable *SetVariable, ok bool) {
+ variable, ok = vc.setVariableMap[name]
+ return variable, ok
+}
+
+// PopulateVariables handles setting the active variables within a VariableConfig's SetVariableMap
+func (vc *VariableConfig) PopulateVariables(variables []InteractiveVariable, presetVariables map[string]string) error {
+ for name, value := range presetVariables {
+ vc.SetVariable(name, value, false, false, "")
+ }
+
+ for _, variable := range variables {
+ _, present := vc.setVariableMap[variable.Name]
+
+ // Variable is present, no need to continue checking
+ if present {
+ vc.setVariableMap[variable.Name].Sensitive = variable.Sensitive
+ vc.setVariableMap[variable.Name].AutoIndent = variable.AutoIndent
+ vc.setVariableMap[variable.Name].Type = variable.Type
+ if err := vc.CheckVariablePattern(variable.Name, variable.Pattern); err != nil {
+ return err
+ }
+ continue
+ }
+
+ // First set default (may be overridden by prompt)
+ vc.SetVariable(variable.Name, variable.Default, variable.Sensitive, variable.AutoIndent, variable.Type)
+
+ // Variable is set to prompt the user
+ if variable.Prompt {
+ // Prompt the user for the variable
+ val, err := vc.prompt(variable)
+
+ if err != nil {
+ return err
+ }
+
+ vc.SetVariable(variable.Name, val, variable.Sensitive, variable.AutoIndent, variable.Type)
+ }
+
+ if err := vc.CheckVariablePattern(variable.Name, variable.Pattern); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// SetVariable sets a variable in a VariableConfig's SetVariableMap
+func (vc *VariableConfig) SetVariable(name, value string, sensitive bool, autoIndent bool, varType VariableType) {
+ vc.setVariableMap[name] = &SetVariable{
+ Variable: Variable{
+ Name: name,
+ Sensitive: sensitive,
+ AutoIndent: autoIndent,
+ Type: varType,
+ },
+ Value: value,
+ }
+}
+
+// CheckVariablePattern checks to see if a current variable is set to a value that matches its pattern
+func (vc *VariableConfig) CheckVariablePattern(name, pattern string) error {
+ if regexp.MustCompile(pattern).MatchString(vc.setVariableMap[name].Value) {
+ return nil
+ }
+
+ return fmt.Errorf("provided value for variable %q does not match pattern %q", name, pattern)
+}
diff --git a/src/types/component.go b/src/types/component.go
index eaeed14bd8..caee8ee680 100644
--- a/src/types/component.go
+++ b/src/types/component.go
@@ -6,6 +6,7 @@ package types
import (
"github.com/defenseunicorns/zarf/src/pkg/utils/exec"
+ "github.com/defenseunicorns/zarf/src/pkg/variables"
"github.com/defenseunicorns/zarf/src/types/extensions"
)
@@ -173,26 +174,17 @@ type ZarfComponentActionDefaults struct {
// ZarfComponentAction represents a single action to run during a zarf package operation
type ZarfComponentAction struct {
- Mute *bool `json:"mute,omitempty" jsonschema:"description=Hide the output of the command during package deployment (default false)"`
- MaxTotalSeconds *int `json:"maxTotalSeconds,omitempty" jsonschema:"description=Timeout in seconds for the command (default to 0, no timeout for cmd actions and 300, 5 minutes for wait actions)"`
- MaxRetries *int `json:"maxRetries,omitempty" jsonschema:"description=Retry the command if it fails up to given number of times (default 0)"`
- Dir *string `json:"dir,omitempty" jsonschema:"description=The working directory to run the command in (default is CWD)"`
- Env []string `json:"env,omitempty" jsonschema:"description=Additional environment variables to set for the command"`
- Cmd string `json:"cmd,omitempty" jsonschema:"description=The command to run. Must specify either cmd or wait for the action to do anything."`
- Shell *exec.Shell `json:"shell,omitempty" jsonschema:"description=(cmd only) Indicates a preference for a shell for the provided cmd to be executed in on supported operating systems"`
- DeprecatedSetVariable string `json:"setVariable,omitempty" jsonschema:"description=[Deprecated] (replaced by setVariables) (onDeploy/cmd only) The name of a variable to update with the output of the command. This variable will be available to all remaining actions and components in the package. This will be removed in Zarf v1.0.0,pattern=^[A-Z0-9_]+$"`
- SetVariables []ZarfComponentActionSetVariable `json:"setVariables,omitempty" jsonschema:"description=(onDeploy/cmd only) An array of variables to update with the output of the command. These variables will be available to all remaining actions and components in the package."`
- Description string `json:"description,omitempty" jsonschema:"description=Description of the action to be displayed during package execution instead of the command"`
- Wait *ZarfComponentActionWait `json:"wait,omitempty" jsonschema:"description=Wait for a condition to be met before continuing. Must specify either cmd or wait for the action. See the 'zarf tools wait-for' command for more info."`
-}
-
-// ZarfComponentActionSetVariable represents a variable that is to be set via an action
-type ZarfComponentActionSetVariable struct {
- Name string `json:"name" jsonschema:"description=The name to be used for the variable,pattern=^[A-Z0-9_]+$"`
- Type VariableType `json:"type,omitempty" jsonschema:"description=Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB),enum=raw,enum=file"`
- Pattern string `json:"pattern,omitempty" jsonschema:"description=An optional regex pattern that a variable value must match before a package deployment can continue."`
- Sensitive bool `json:"sensitive,omitempty" jsonschema:"description=Whether to mark this variable as sensitive to not print it in the Zarf log"`
- AutoIndent bool `json:"autoIndent,omitempty" jsonschema:"description=Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_."`
+ Mute *bool `json:"mute,omitempty" jsonschema:"description=Hide the output of the command during package deployment (default false)"`
+ MaxTotalSeconds *int `json:"maxTotalSeconds,omitempty" jsonschema:"description=Timeout in seconds for the command (default to 0, no timeout for cmd actions and 300, 5 minutes for wait actions)"`
+ MaxRetries *int `json:"maxRetries,omitempty" jsonschema:"description=Retry the command if it fails up to given number of times (default 0)"`
+ Dir *string `json:"dir,omitempty" jsonschema:"description=The working directory to run the command in (default is CWD)"`
+ Env []string `json:"env,omitempty" jsonschema:"description=Additional environment variables to set for the command"`
+ Cmd string `json:"cmd,omitempty" jsonschema:"description=The command to run. Must specify either cmd or wait for the action to do anything."`
+ Shell *exec.Shell `json:"shell,omitempty" jsonschema:"description=(cmd only) Indicates a preference for a shell for the provided cmd to be executed in on supported operating systems"`
+ DeprecatedSetVariable string `json:"setVariable,omitempty" jsonschema:"description=[Deprecated] (replaced by setVariables) (onDeploy/cmd only) The name of a variable to update with the output of the command. This variable will be available to all remaining actions and components in the package. This will be removed in Zarf v1.0.0,pattern=^[A-Z0-9_]+$"`
+ SetVariables []variables.Variable `json:"setVariables,omitempty" jsonschema:"description=(onDeploy/cmd only) An array of variables to update with the output of the command. These variables will be available to all remaining actions and components in the package."`
+ Description string `json:"description,omitempty" jsonschema:"description=Description of the action to be displayed during package execution instead of the command"`
+ Wait *ZarfComponentActionWait `json:"wait,omitempty" jsonschema:"description=Wait for a condition to be met before continuing. Must specify either cmd or wait for the action. See the 'zarf tools wait-for' command for more info."`
}
// ZarfComponentActionWait specifies a condition to wait for before continuing
diff --git a/src/types/package.go b/src/types/package.go
index 7a4e91a503..4f3f222fb0 100644
--- a/src/types/package.go
+++ b/src/types/package.go
@@ -4,6 +4,8 @@
// Package types contains all the types used by Zarf.
package types
+import "github.com/defenseunicorns/zarf/src/pkg/variables"
+
// ZarfPackageKind is an enum of the different kinds of Zarf packages.
type ZarfPackageKind string
@@ -16,12 +18,12 @@ const (
// ZarfPackage the top-level structure of a Zarf config file.
type ZarfPackage struct {
- Kind ZarfPackageKind `json:"kind" jsonschema:"description=The kind of Zarf package,enum=ZarfInitConfig,enum=ZarfPackageConfig,default=ZarfPackageConfig"`
- Metadata ZarfMetadata `json:"metadata,omitempty" jsonschema:"description=Package metadata"`
- Build ZarfBuildData `json:"build,omitempty" jsonschema:"description=Zarf-generated package build data"`
- Components []ZarfComponent `json:"components" jsonschema:"description=List of components to deploy in this package"`
- Constants []ZarfPackageConstant `json:"constants,omitempty" jsonschema:"description=Constant template values applied on deploy for K8s resources"`
- Variables []ZarfPackageVariable `json:"variables,omitempty" jsonschema:"description=Variable template values applied on deploy for K8s resources"`
+ Kind ZarfPackageKind `json:"kind" jsonschema:"description=The kind of Zarf package,enum=ZarfInitConfig,enum=ZarfPackageConfig,default=ZarfPackageConfig"`
+ Metadata ZarfMetadata `json:"metadata,omitempty" jsonschema:"description=Package metadata"`
+ Build ZarfBuildData `json:"build,omitempty" jsonschema:"description=Zarf-generated package build data"`
+ Components []ZarfComponent `json:"components" jsonschema:"description=List of components to deploy in this package"`
+ Constants []variables.Constant `json:"constants,omitempty" jsonschema:"description=Constant template values applied on deploy for K8s resources"`
+ Variables []variables.InteractiveVariable `json:"variables,omitempty" jsonschema:"description=Variable template values applied on deploy for K8s resources"`
}
// IsInitConfig returns whether a Zarf package is an init config.
@@ -71,25 +73,3 @@ type ZarfBuildData struct {
LastNonBreakingVersion string `json:"lastNonBreakingVersion,omitempty" jsonschema:"description=The minimum version of Zarf that does not have breaking package structure changes"`
Flavor string `json:"flavor,omitempty" jsonschema:"description=The flavor of Zarf used to build this package"`
}
-
-// ZarfPackageVariable are variables that can be used to dynamically template K8s resources.
-type ZarfPackageVariable struct {
- Name string `json:"name" jsonschema:"description=The name to be used for the variable,pattern=^[A-Z0-9_]+$"`
- Description string `json:"description,omitempty" jsonschema:"description=A description of the variable to be used when prompting the user a value"`
- Default string `json:"default,omitempty" jsonschema:"description=The default value to use for the variable"`
- Prompt bool `json:"prompt,omitempty" jsonschema:"description=Whether to prompt the user for input for this variable"`
- Sensitive bool `json:"sensitive,omitempty" jsonschema:"description=Whether to mark this variable as sensitive to not print it in the Zarf log"`
- AutoIndent bool `json:"autoIndent,omitempty" jsonschema:"description=Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_."`
- Pattern string `json:"pattern,omitempty" jsonschema:"description=An optional regex pattern that a variable value must match before a package can be deployed."`
- Type VariableType `json:"type,omitempty" jsonschema:"description=Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB),enum=raw,enum=file"`
-}
-
-// ZarfPackageConstant are constants that can be used to dynamically template K8s resources.
-type ZarfPackageConstant struct {
- Name string `json:"name" jsonschema:"description=The name to be used for the constant,pattern=^[A-Z0-9_]+$"`
- Value string `json:"value" jsonschema:"description=The value to set for the constant during deploy"`
- // Include a description that will only be displayed during package create/deploy confirm prompts
- Description string `json:"description,omitempty" jsonschema:"description=A description of the constant to explain its purpose on package create or deploy confirmation prompts"`
- AutoIndent bool `json:"autoIndent,omitempty" jsonschema:"description=Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_CONST_."`
- Pattern string `json:"pattern,omitempty" jsonschema:"description=An optional regex pattern that a constant value must match before a package can be created."`
-}
diff --git a/src/types/packager.go b/src/types/packager.go
index 857683a529..0089b2ae07 100644
--- a/src/types/packager.go
+++ b/src/types/packager.go
@@ -4,11 +4,6 @@
// Package types contains all the types used by Zarf.
package types
-import (
- "fmt"
- "regexp"
-)
-
// PackagerConfig is the main struct that the packager uses to hold high-level options.
type PackagerConfig struct {
// CreateOpts tracks the user-defined options used to create the package
@@ -43,29 +38,4 @@ type PackagerConfig struct {
// The package data
Pkg ZarfPackage
-
- // The active zarf state
- State *ZarfState
-
- // Variables set by the user
- SetVariableMap map[string]*ZarfSetVariable
-}
-
-// SetVariable sets a value for a variable in PackagerConfig.SetVariableMap.
-func (cfg *PackagerConfig) SetVariable(name, value string, sensitive bool, autoIndent bool, varType VariableType) {
- cfg.SetVariableMap[name] = &ZarfSetVariable{
- Name: name,
- Value: value,
- Sensitive: sensitive,
- AutoIndent: autoIndent,
- Type: varType,
- }
-}
-
-// CheckVariablePattern checks to see if a variable is set to a value that matches its pattern.
-func (cfg *PackagerConfig) CheckVariablePattern(name, pattern string) error {
- if regexp.MustCompile(pattern).MatchString(cfg.SetVariableMap[name].Value) {
- return nil
- }
- return fmt.Errorf("provided value for variable %q does not match pattern \"%s\"", name, pattern)
}
diff --git a/src/types/runtime.go b/src/types/runtime.go
index 4df0299175..3d9ea5d09a 100644
--- a/src/types/runtime.go
+++ b/src/types/runtime.go
@@ -8,13 +8,6 @@ import (
"time"
)
-const (
- // RawVariableType is the default type for a Zarf package variable
- RawVariableType VariableType = "raw"
- // FileVariableType is a type for a Zarf package variable that loads its contents from a file
- FileVariableType VariableType = "file"
-)
-
// Zarf looks for these strings in zarf.yaml to make dynamic changes
const (
ZarfPackageTemplatePrefix = "###ZARF_PKG_TMPL_"
@@ -23,9 +16,6 @@ const (
ZarfComponentName = "###ZARF_COMPONENT_NAME###"
)
-// VariableType represents a type of a Zarf package variable
-type VariableType string
-
// ZarfCommonOptions tracks the user-defined preferences used across commands.
type ZarfCommonOptions struct {
Confirm bool `json:"confirm" jsonschema:"description=Verify that Zarf should perform an action"`
@@ -135,15 +125,6 @@ type ZarfSplitPackageData struct {
Count int `json:"count" jsonschema:"description=The number of parts the package is split into"`
}
-// ZarfSetVariable tracks internal variables that have been set during this run of Zarf
-type ZarfSetVariable struct {
- Name string `json:"name" jsonschema:"description=The name to be used for the variable,pattern=^[A-Z0-9_]+$"`
- Sensitive bool `json:"sensitive,omitempty" jsonschema:"description=Whether to mark this variable as sensitive to not print it in the Zarf log"`
- AutoIndent bool `json:"autoIndent,omitempty" jsonschema:"description=Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_."`
- Value string `json:"value" jsonschema:"description=The value the variable is currently set with"`
- Type VariableType `json:"type,omitempty" jsonschema:"description=Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB),enum=raw,enum=file"`
-}
-
// ConnectString contains information about a connection made with Zarf connect.
type ConnectString struct {
Description string `json:"description" jsonschema:"description=Descriptive text that explains what the resource you would be connecting to is used for"`
diff --git a/zarf.schema.json b/zarf.schema.json
index 69f4aae9d0..633e73110e 100644
--- a/zarf.schema.json
+++ b/zarf.schema.json
@@ -40,6 +40,40 @@
"^x-": {}
}
},
+ "Constant": {
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "pattern": "^[A-Z0-9_]+$",
+ "type": "string",
+ "description": "The name to be used for the constant"
+ },
+ "value": {
+ "type": "string",
+ "description": "The value to set for the constant during deploy"
+ },
+ "description": {
+ "type": "string",
+ "description": "A description of the constant to explain its purpose on package create or deploy confirmation prompts"
+ },
+ "autoIndent": {
+ "type": "boolean",
+ "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_CONST_."
+ },
+ "pattern": {
+ "type": "string",
+ "description": "An optional regex pattern that a constant value must match before a package can be created."
+ }
+ },
+ "additionalProperties": false,
+ "type": "object",
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
"DeprecatedZarfComponentScripts": {
"properties": {
"showOutput": {
@@ -82,6 +116,33 @@
"^x-": {}
}
},
+ "InteractiveVariable": {
+ "required": [
+ "Variable"
+ ],
+ "properties": {
+ "Variable": {
+ "$ref": "#/definitions/Variable"
+ },
+ "description": {
+ "type": "string",
+ "description": "A description of the variable to be used when prompting the user a value"
+ },
+ "default": {
+ "type": "string",
+ "description": "The default value to use for the variable"
+ },
+ "prompt": {
+ "type": "boolean",
+ "description": "Whether to prompt the user for input for this variable"
+ }
+ },
+ "additionalProperties": false,
+ "type": "object",
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
"Shell": {
"properties": {
"windows": {
@@ -125,6 +186,43 @@
"^x-": {}
}
},
+ "Variable": {
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "pattern": "^[A-Z0-9_]+$",
+ "type": "string",
+ "description": "The name to be used for the variable"
+ },
+ "sensitive": {
+ "type": "boolean",
+ "description": "Whether to mark this variable as sensitive to not print it in the log"
+ },
+ "autoIndent": {
+ "type": "boolean",
+ "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_."
+ },
+ "pattern": {
+ "type": "string",
+ "description": "An optional regex pattern that a variable value must match before a package deployment can continue."
+ },
+ "type": {
+ "enum": [
+ "raw",
+ "file"
+ ],
+ "type": "string",
+ "description": "Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB)"
+ }
+ },
+ "additionalProperties": false,
+ "type": "object",
+ "patternProperties": {
+ "^x-": {}
+ }
+ },
"ZarfBuildData": {
"required": [
"terminal",
@@ -448,7 +546,7 @@
"setVariables": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/ZarfComponentActionSetVariable"
+ "$ref": "#/definitions/Variable"
},
"type": "array",
"description": "(onDeploy/cmd only) An array of variables to update with the output of the command. These variables will be available to all remaining actions and components in the package."
@@ -549,43 +647,6 @@
"^x-": {}
}
},
- "ZarfComponentActionSetVariable": {
- "required": [
- "name"
- ],
- "properties": {
- "name": {
- "pattern": "^[A-Z0-9_]+$",
- "type": "string",
- "description": "The name to be used for the variable"
- },
- "type": {
- "enum": [
- "raw",
- "file"
- ],
- "type": "string",
- "description": "Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB)"
- },
- "pattern": {
- "type": "string",
- "description": "An optional regex pattern that a variable value must match before a package deployment can continue."
- },
- "sensitive": {
- "type": "boolean",
- "description": "Whether to mark this variable as sensitive to not print it in the Zarf log"
- },
- "autoIndent": {
- "type": "boolean",
- "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_."
- }
- },
- "additionalProperties": false,
- "type": "object",
- "patternProperties": {
- "^x-": {}
- }
- },
"ZarfComponentActionWait": {
"properties": {
"cluster": {
@@ -1043,7 +1104,7 @@
"constants": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/ZarfPackageConstant"
+ "$ref": "#/definitions/Constant"
},
"type": "array",
"description": "Constant template values applied on deploy for K8s resources"
@@ -1051,7 +1112,7 @@
"variables": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/ZarfPackageVariable"
+ "$ref": "#/definitions/InteractiveVariable"
},
"type": "array",
"description": "Variable template values applied on deploy for K8s resources"
@@ -1062,89 +1123,6 @@
"patternProperties": {
"^x-": {}
}
- },
- "ZarfPackageConstant": {
- "required": [
- "name",
- "value"
- ],
- "properties": {
- "name": {
- "pattern": "^[A-Z0-9_]+$",
- "type": "string",
- "description": "The name to be used for the constant"
- },
- "value": {
- "type": "string",
- "description": "The value to set for the constant during deploy"
- },
- "description": {
- "type": "string",
- "description": "A description of the constant to explain its purpose on package create or deploy confirmation prompts"
- },
- "autoIndent": {
- "type": "boolean",
- "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_CONST_."
- },
- "pattern": {
- "type": "string",
- "description": "An optional regex pattern that a constant value must match before a package can be created."
- }
- },
- "additionalProperties": false,
- "type": "object",
- "patternProperties": {
- "^x-": {}
- }
- },
- "ZarfPackageVariable": {
- "required": [
- "name"
- ],
- "properties": {
- "name": {
- "pattern": "^[A-Z0-9_]+$",
- "type": "string",
- "description": "The name to be used for the variable"
- },
- "description": {
- "type": "string",
- "description": "A description of the variable to be used when prompting the user a value"
- },
- "default": {
- "type": "string",
- "description": "The default value to use for the variable"
- },
- "prompt": {
- "type": "boolean",
- "description": "Whether to prompt the user for input for this variable"
- },
- "sensitive": {
- "type": "boolean",
- "description": "Whether to mark this variable as sensitive to not print it in the Zarf log"
- },
- "autoIndent": {
- "type": "boolean",
- "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_."
- },
- "pattern": {
- "type": "string",
- "description": "An optional regex pattern that a variable value must match before a package can be deployed."
- },
- "type": {
- "enum": [
- "raw",
- "file"
- ],
- "type": "string",
- "description": "Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB)"
- }
- },
- "additionalProperties": false,
- "type": "object",
- "patternProperties": {
- "^x-": {}
- }
}
}
}