Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: imported vars as override values #423

Merged
merged 15 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/overrides.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ The `value` is the value to set at the `path`. Values can be simple values such
value:
customAnnotation: "customValue"
```
If [importing](../README.md#importingexporting-variables) a variable from another package, that variable can also be used to set a value, using the template syntax `${...}`
decleaver marked this conversation as resolved.
Show resolved Hide resolved

### Variables
Variables are similar to [values](#values) in that they allow users to override values in a Zarf package component's underlying Helm chart; they also share a similar syntax. However, unlike `values`, `variables` can be overridden at deploy time. For example, consider the following `variables`:
Expand Down
32 changes: 24 additions & 8 deletions src/pkg/bundle/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/AlecAivazis/survey/v2"
Expand Down Expand Up @@ -166,7 +167,7 @@ func deployPackages(packages []types.Package, resume bool, b *Bundle, zarfPackag
SetVariables: pkgVars,
}

valuesOverrides, err := b.loadChartOverrides(pkg)
valuesOverrides, err := b.loadChartOverrides(pkg, pkgVars)
if err != nil {
return err
}
Expand Down Expand Up @@ -274,15 +275,15 @@ func (b *Bundle) confirmBundleDeploy() (confirm bool) {
}

// loadChartOverrides converts a helm path to a ValuesOverridesMap config for Zarf
func (b *Bundle) loadChartOverrides(pkg types.Package) (ZarfOverrideMap, error) {
func (b *Bundle) loadChartOverrides(pkg types.Package, pkgVars map[string]string) (ZarfOverrideMap, error) {

// Create a nested map to hold the values
overrideMap := make(map[string]map[string]*values.Options)

// Loop through each package component's charts and process overrides
for componentName, component := range pkg.Overrides {
for chartName, chart := range component {
err := b.processOverrideValues(&overrideMap, &chart.Values, componentName, chartName)
err := b.processOverrideValues(&overrideMap, &chart.Values, componentName, chartName, pkgVars)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -324,10 +325,10 @@ func (b *Bundle) loadChartOverrides(pkg types.Package) (ZarfOverrideMap, error)
}

// processOverrideValues processes a bundles values overrides and adds them to the override map
func (b *Bundle) processOverrideValues(overrideMap *map[string]map[string]*values.Options, values *[]types.BundleChartValue, componentName string, chartName string) error {
func (b *Bundle) processOverrideValues(overrideMap *map[string]map[string]*values.Options, values *[]types.BundleChartValue, componentName string, chartName string, pkgVars map[string]string) error {
for _, v := range *values {
// Add the override to the map, or return an error if the path is invalid
if err := addOverrideValue(*overrideMap, componentName, chartName, v.Path, v.Value); err != nil {
if err := addOverrideValue(*overrideMap, componentName, chartName, v.Path, v.Value, pkgVars); err != nil {
return err
}
}
Expand All @@ -340,7 +341,7 @@ func (b *Bundle) processOverrideVariables(overrideMap *map[string]map[string]*va
var overrideVal interface{}
// check for override in env vars
if envVarOverride, exists := os.LookupEnv(strings.ToUpper(config.EnvVarPrefix + v.Name)); exists {
if err := addOverrideValue(*overrideMap, componentName, chartName, v.Path, envVarOverride); err != nil {
if err := addOverrideValue(*overrideMap, componentName, chartName, v.Path, envVarOverride, nil); err != nil {
return err
}
continue
Expand All @@ -363,7 +364,7 @@ func (b *Bundle) processOverrideVariables(overrideMap *map[string]map[string]*va
}

// Add the override to the map, or return an error if the path is invalid
if err := addOverrideValue(*overrideMap, componentName, chartName, v.Path, overrideVal); err != nil {
if err := addOverrideValue(*overrideMap, componentName, chartName, v.Path, overrideVal, nil); err != nil {
return err
}

Expand All @@ -372,7 +373,7 @@ func (b *Bundle) processOverrideVariables(overrideMap *map[string]map[string]*va
}

// addOverrideValue adds a value to a ZarfOverrideMap
func addOverrideValue(overrides map[string]map[string]*values.Options, component string, chart string, valuePath string, value interface{}) error {
func addOverrideValue(overrides map[string]map[string]*values.Options, component string, chart string, valuePath string, value interface{}, pkgVars map[string]string) error {
// Create the component map if it doesn't exist
if _, ok := overrides[component]; !ok {
overrides[component] = make(map[string]*values.Options)
Expand Down Expand Up @@ -409,6 +410,21 @@ func addOverrideValue(overrides map[string]map[string]*values.Options, component
val := fmt.Sprintf("%s=%s", valuePath, j)
overrides[component][chart].JSONValues = append(overrides[component][chart].JSONValues, val)
default:
// Check for any templated variables if pkgVars set
decleaver marked this conversation as resolved.
Show resolved Hide resolved
if pkgVars != nil {
// Regular expression to get text in ${...}
re := regexp.MustCompile(`\${([^}]+)}`)
templatedVariable := fmt.Sprintf("%v", v)
// Get the variable name inside of ${...}
// returns slice with the templated variable and the variable name
variableName := re.FindStringSubmatch(templatedVariable)
// If we have a templated variable, get the value from pkgVars
if len(variableName) == 2 {
if varValue, ok := pkgVars[variableName[1]]; ok {
value = varValue
}
}
}
// handle default case of simple values like strings and numbers
helmVal := fmt.Sprintf("%s=%v", valuePath, value)
overrides[component][chart].Values = append(overrides[component][chart].Values, helmVal)
Expand Down
28 changes: 28 additions & 0 deletions src/test/bundles/12-exported-pkg-vars/uds-bundle.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
kind: UDSBundle
metadata:
name: export-vars
description: testing a bundle using exported vars from zarf package
version: 0.0.1

packages:
- name: output-var
repository: localhost:888/output-var
ref: 0.0.1
exports:
- name: COLOR

- name: helm-overrides
path: "../../packages/helm"
ref: 0.0.1
imports:
- name: COLOR
package: output-var

overrides:
podinfo-component:
unicorn-podinfo:
values:
- path: "podinfo.replicaCount"
value: 1
- path: "podinfo.ui.color"
value: ${COLOR}
decleaver marked this conversation as resolved.
Show resolved Hide resolved
decleaver marked this conversation as resolved.
Show resolved Hide resolved
28 changes: 28 additions & 0 deletions src/test/e2e/variable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,31 @@ func TestVariablePrecedence(t *testing.T) {

remove(t, bundlePath)
}

func TestZarfPackageExportVarsAsGlobalBundleVars(t *testing.T) {
deployZarfInit(t)
zarfPkgPath1 := "src/test/packages/no-cluster/output-var"
e2e.CreateZarfPkg(t, zarfPkgPath1, false)

e2e.SetupDockerRegistry(t, 888)
defer e2e.TeardownRegistry(t, 888)

pkg := filepath.Join(zarfPkgPath1, fmt.Sprintf("zarf-package-output-var-%s-0.0.1.tar.zst", e2e.Arch))
zarfPublish(t, pkg, "localhost:888")

e2e.HelmDepUpdate(t, "src/test/packages/helm/unicorn-podinfo")
e2e.CreateZarfPkg(t, "src/test/packages/helm", false)
bundleDir := "src/test/bundles/12-exported-pkg-vars"
bundlePath := filepath.Join(bundleDir, fmt.Sprintf("uds-bundle-export-vars-%s-0.0.1.tar.zst", e2e.Arch))

createLocal(t, bundleDir, e2e.Arch)
deploy(t, bundlePath)

// check variables overrides
cmd := strings.Split("zarf tools kubectl get deploy -n podinfo unicorn-podinfo -o=jsonpath='{.spec.template.spec.containers[0].env[?(@.name==\"PODINFO_UI_COLOR\")].value}'", " ")
outputUIColor, _, err := e2e.UDS(cmd...)
require.Equal(t, "'orange'", outputUIColor)
require.NoError(t, err)

remove(t, bundlePath)
}
3 changes: 3 additions & 0 deletions src/test/packages/no-cluster/output-var/zarf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ components:
echo "shared var in output-var pkg: "${ZARF_VAR_DOMAIN}""
- cmd: |
echo "output-var SPECIFIC_PKG_VAR = "${ZARF_VAR_SPECIFIC_PKG_VAR}""
- cmd: echo "orange"
setVariables:
- name: COLOR
Loading