Repository: rancher/fleet
Pull request #1431 (2023-03-22 15:59:57)

Don't ignore config map reference in valuesFrom list element
Refers to https://github.com/rancher/fleet/issues/1432

If both references are provided in a `valuesFrom` list element, use both.


## TODO
- [x] add test from manual testing at https://github.com/manno/fleet-experiments/tree/valuesFrom


Patch:
diff --git a/.github/workflows/fleet-upgrade-in-rancher.yml b/.github/workflows/fleet-upgrade-in-rancher.yml
index 41f8e5e5..49b625fc 100644
--- a/.github/workflows/fleet-upgrade-in-rancher.yml
+++ b/.github/workflows/fleet-upgrade-in-rancher.yml
@@ -137,8 +137,8 @@ jobs:
       -
         name: Create example workload
         run: |
-          kubectl apply -n fleet-local -f e2e/assets/gitrepo-simple.yaml
-          kubectl apply -n fleet-default -f e2e/assets/gitrepo-simple.yaml
+          kubectl apply -n fleet-local -f e2e/assets/fleet-upgrade/gitrepo-simple.yaml
+          kubectl apply -n fleet-default -f e2e/assets/fleet-upgrade/gitrepo-simple.yaml
       -
         name: Deploy latest fleet
         env:
diff --git a/pkg/helmdeployer/deployer.go b/pkg/helmdeployer/deployer.go
index 29cac9d9..7c6c7732 100644
--- a/pkg/helmdeployer/deployer.go
+++ b/pkg/helmdeployer/deployer.go
@@ -436,39 +436,46 @@ func (h *Helm) getValues(options fleet.BundleDeploymentOptions, defaultNamespace
 	if !h.template {
 		for _, valuesFrom := range options.Helm.ValuesFrom {
 			var tempValues map[string]interface{}
-			if valuesFrom.SecretKeyRef != nil {
-				name := valuesFrom.SecretKeyRef.Name
-				namespace := valuesFrom.SecretKeyRef.Namespace
+			if valuesFrom.ConfigMapKeyRef != nil {
+				name := valuesFrom.ConfigMapKeyRef.Name
+				namespace := valuesFrom.ConfigMapKeyRef.Namespace
 				if namespace == "" {
 					namespace = defaultNamespace
 				}
-				key := valuesFrom.SecretKeyRef.Key
+				key := valuesFrom.ConfigMapKeyRef.Key
 				if key == "" {
 					key = DefaultKey
 				}
-				secret, err := h.secretCache.Get(namespace, name)
+				configMap, err := h.configmapCache.Get(namespace, name)
 				if err != nil {
 					return nil, err
 				}
-				tempValues, err = processValuesFromObject(name, namespace, key, secret, nil)
+				tempValues, err = valuesFromConfigMap(name, namespace, key, configMap)
 				if err != nil {
 					return nil, err
 				}
-			} else if valuesFrom.ConfigMapKeyRef != nil {
-				name := valuesFrom.ConfigMapKeyRef.Name
-				namespace := valuesFrom.ConfigMapKeyRef.Namespace
+			}
+			if tempValues != nil {
+				values = mergeValues(values, tempValues)
+				tempValues = nil
+			}
+
+			// merge secret last to be compatible with fleet <= 0.6.0
+			if valuesFrom.SecretKeyRef != nil {
+				name := valuesFrom.SecretKeyRef.Name
+				namespace := valuesFrom.SecretKeyRef.Namespace
 				if namespace == "" {
 					namespace = defaultNamespace
 				}
-				key := valuesFrom.ConfigMapKeyRef.Key
+				key := valuesFrom.SecretKeyRef.Key
 				if key == "" {
 					key = DefaultKey
 				}
-				configMap, err := h.configmapCache.Get(namespace, name)
+				secret, err := h.secretCache.Get(namespace, name)
 				if err != nil {
 					return nil, err
 				}
-				tempValues, err = processValuesFromObject(name, namespace, key, nil, configMap)
+				tempValues, err = valuesFromSecret(name, namespace, key, secret)
 				if err != nil {
 					return nil, err
 				}
@@ -731,24 +738,34 @@ func deleteHistory(cfg action.Configuration, bundleID string) error {
 	return nil
 }
 
-func processValuesFromObject(name, namespace, key string, secret *corev1.Secret, configMap *corev1.ConfigMap) (map[string]interface{}, error) {
+func valuesFromSecret(name, namespace, key string, secret *corev1.Secret) (map[string]interface{}, error) {
 	var m map[string]interface{}
-	if secret != nil {
-		values, ok := secret.Data[key]
-		if !ok {
-			return nil, fmt.Errorf("key %s is missing from secret %s/%s, can't use it in valuesFrom", key, namespace, name)
-		}
-		if err := yaml.Unmarshal(values, &m); err != nil {
-			return nil, err
-		}
-	} else if configMap != nil {
-		values, ok := configMap.Data[key]
-		if !ok {
-			return nil, fmt.Errorf("key %s is missing from configmap %s/%s, can't use it in valuesFrom", key, namespace, name)
-		}
-		if err := yaml.Unmarshal([]byte(values), &m); err != nil {
-			return nil, err
-		}
+	if secret == nil {
+		return m, nil
+	}
+
+	values, ok := secret.Data[key]
+	if !ok {
+		return nil, fmt.Errorf("key %s is missing from secret %s/%s, can't use it in valuesFrom", key, namespace, name)
+	}
+	if err := yaml.Unmarshal(values, &m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+func valuesFromConfigMap(name, namespace, key string, configMap *corev1.ConfigMap) (map[string]interface{}, error) {
+	var m map[string]interface{}
+	if configMap == nil {
+		return m, nil
+	}
+
+	values, ok := configMap.Data[key]
+	if !ok {
+		return nil, fmt.Errorf("key %s is missing from configmap %s/%s, can't use it in valuesFrom", key, namespace, name)
+	}
+	if err := yaml.Unmarshal([]byte(values), &m); err != nil {
+		return nil, err
 	}
 	return m, nil
 }
@@ -764,19 +781,21 @@ func mergeMaps(base, other map[string]string) map[string]string {
 	return result
 }
 
-// mergeValues merges source and destination map, preferring values
+// mergeValues merges source and destination map, preferring values over maps
 // from the source values. This is slightly adapted from:
 // https://github.com/helm/helm/blob/2332b480c9cb70a0d8a85247992d6155fbe82416/cmd/helm/install.go#L359
 func mergeValues(dest, src map[string]interface{}) map[string]interface{} {
 	for k, v := range src {
 		// If the key doesn't exist already, then just set the key to that value
 		if _, exists := dest[k]; !exists {
+			// new key
 			dest[k] = v
 			continue
 		}
 		nextMap, ok := v.(map[string]interface{})
 		// If it isn't another map, overwrite the value
 		if !ok {
+			// new key is not a map, overwrite existing key as we prefer values over maps
 			dest[k] = v
 			continue
 		}


Test patch:
diff --git a/e2e/assets/gitrepo-simple.yaml b/e2e/assets/fleet-upgrade/gitrepo-simple.yaml
similarity index 100%
rename from e2e/assets/gitrepo-simple.yaml
rename to e2e/assets/fleet-upgrade/gitrepo-simple.yaml
diff --git a/e2e/assets/gitrepo-template.yaml b/e2e/assets/gitrepo-template.yaml
new file mode 100644
index 00000000..8f4f3315
--- /dev/null
+++ b/e2e/assets/gitrepo-template.yaml
@@ -0,0 +1,14 @@
+kind: GitRepo
+apiVersion: fleet.cattle.io/v1alpha1
+metadata:
+  name: {{ .Name }}
+
+spec:
+  repo: https://github.com/rancher/fleet-test-data
+  branch: {{ .Branch }}
+  paths:
+    {{- range .Paths}}
+    - {{.}}
+    {{- end}}
+
+  targetNamespace: {{ .TargetNamespace }}
diff --git a/e2e/assets/simple/gitrepo.yaml b/e2e/assets/installation/verify.yaml
similarity index 100%
rename from e2e/assets/simple/gitrepo.yaml
rename to e2e/assets/installation/verify.yaml
diff --git a/e2e/assets/single-cluster/values-from-configmap.yaml b/e2e/assets/single-cluster/values-from-configmap.yaml
new file mode 100644
index 00000000..174c1404
--- /dev/null
+++ b/e2e/assets/single-cluster/values-from-configmap.yaml
@@ -0,0 +1,6 @@
+name: configmap overrides values from fleet.yaml
+config: config option
+options:
+  onlyconfigmap: configmap option
+  english:
+    name: configmap override
diff --git a/e2e/assets/single-cluster/values-from-secret.yaml b/e2e/assets/single-cluster/values-from-secret.yaml
new file mode 100644
index 00000000..0380ae0a
--- /dev/null
+++ b/e2e/assets/single-cluster/values-from-secret.yaml
@@ -0,0 +1,6 @@
+name: secret overrides values from fleet.yaml
+secret: xyz secret
+options:
+  onlysecret: secret option
+  english:
+    name: secret override
diff --git a/e2e/installation/verify_test.go b/e2e/installation/verify_test.go
index 3f064a18..d2b9f737 100644
--- a/e2e/installation/verify_test.go
+++ b/e2e/installation/verify_test.go
@@ -80,7 +80,7 @@ var _ = Describe("Fleet Installation", func() {
 	When("Deploying another bundle still works", func() {
 		var tmpdir string
 		BeforeEach(func() {
-			asset = "simple/gitrepo.yaml"
+			asset = "installation/verify.yaml"
 		})
 
 		JustBeforeEach(func() {
diff --git a/e2e/multi-cluster/bundle_namespace_mapping_test.go b/e2e/multi-cluster/bundle_namespace_mapping_test.go
index e1e6adbd..a74ea381 100644
--- a/e2e/multi-cluster/bundle_namespace_mapping_test.go
+++ b/e2e/multi-cluster/bundle_namespace_mapping_test.go
@@ -1,8 +1,6 @@
-package mc_examples_test
+package multicluster_test
 
 import (
-	"os"
-	"path"
 	"time"
 
 	"github.com/rancher/fleet/e2e/testenv"
@@ -20,7 +18,6 @@ var _ = Describe("Bundle Namespace Mapping", Label("difficult"), func() {
 		asset     string
 		namespace string
 		data      any
-		tmpdir    string
 
 		interval = 2 * time.Second
 		duration = 30 * time.Second
@@ -40,19 +37,13 @@ var _ = Describe("Bundle Namespace Mapping", Label("difficult"), func() {
 	})
 
 	JustBeforeEach(func() {
-		tmpdir, _ = os.MkdirTemp("", "fleet-")
-		output := path.Join(tmpdir, testenv.RandomFilename("manifests.yaml"))
-		err := testenv.Template(output, testenv.AssetPath(asset), data)
+		err := testenv.ApplyTemplate(k.Namespace(namespace), testenv.AssetPath(asset), data)
 		Expect(err).ToNot(HaveOccurred())
-
-		out, err := k.Namespace(namespace).Apply("-f", output)
-		Expect(err).ToNot(HaveOccurred(), out)
 	})
 
 	AfterEach(func() {
 		out, err := k.Delete("ns", namespace)
 		Expect(err).ToNot(HaveOccurred(), out)
-		os.RemoveAll(tmpdir)
 	})
 
 	Context("with bundlenamespacemapping", func() {
diff --git a/e2e/multi-cluster/suite_test.go b/e2e/multi-cluster/suite_test.go
index 1ad01194..f3fd196e 100644
--- a/e2e/multi-cluster/suite_test.go
+++ b/e2e/multi-cluster/suite_test.go
@@ -1,4 +1,5 @@
-package mc_examples_test
+// Package multicluster contains e2e tests deploying to multiple clusters. The tests use kubectl to apply manifests. Expectations are verified by checking cluster resources. Assets refer to the https://github.com/rancher/fleet-test-data git repo.
+package multicluster_test
 
 import (
 	"testing"
diff --git a/e2e/require-secrets/gitrepo_test.go b/e2e/require-secrets/gitrepo_test.go
index c77b722f..0f4daf0a 100644
--- a/e2e/require-secrets/gitrepo_test.go
+++ b/e2e/require-secrets/gitrepo_test.go
@@ -45,23 +45,20 @@ var _ = Describe("Git Repo", func() {
 		)
 		Expect(err).ToNot(HaveOccurred(), out)
 
-		tmpdir, _ = os.MkdirTemp("", "fleet-")
-		repodir = path.Join(tmpdir, "repo")
-		repo, err = gh.Create(repodir, testenv.AssetPath("gitrepo/sleeper-chart"), "examples")
-		Expect(err).ToNot(HaveOccurred())
-
-		gitrepo := path.Join(tmpdir, "gitrepo.yaml")
-		err = testenv.Template(gitrepo, testenv.AssetPath("gitrepo/gitrepo.yaml"), struct {
+		err = testenv.ApplyTemplate(k, testenv.AssetPath("gitrepo/gitrepo.yaml"), struct {
 			Repo   string
 			Branch string
 		}{
 			gh.URL,
 			gh.Branch,
 		})
+		Expect(err).ToNot(HaveOccurred(), out)
+
+		tmpdir, _ = os.MkdirTemp("", "fleet-")
+		repodir = path.Join(tmpdir, "repo")
+		repo, err = gh.Create(repodir, testenv.AssetPath("gitrepo/sleeper-chart"), "examples")
 		Expect(err).ToNot(HaveOccurred())
 
-		out, err = k.Apply("-f", gitrepo)
-		Expect(err).ToNot(HaveOccurred(), out)
 	})
 
 	AfterEach(func() {
diff --git a/e2e/single-cluster/bundle_diffs_test.go b/e2e/single-cluster/bundle_diffs_test.go
index 913c7dfd..ec29eb19 100644
--- a/e2e/single-cluster/bundle_diffs_test.go
+++ b/e2e/single-cluster/bundle_diffs_test.go
@@ -1,4 +1,4 @@
-package examples_test
+package singlecluster_test
 
 import (
 	"encoding/json"
@@ -62,7 +62,7 @@ var _ = Describe("BundleDiffs", func() {
 				}
 
 				return false
-			}).Should(BeTrue(), "bundledepoloyment should be deleted")
+			}).Should(BeTrue(), "bundledeployment should be deleted")
 		})
 	})
 
diff --git a/e2e/single-cluster/helm_verify_test.go b/e2e/single-cluster/helm_verify_test.go
index 543359d4..e8aa1704 100644
--- a/e2e/single-cluster/helm_verify_test.go
+++ b/e2e/single-cluster/helm_verify_test.go
@@ -1,4 +1,4 @@
-package examples_test
+package singlecluster_test
 
 import (
 	"github.com/rancher/fleet/e2e/testenv"
diff --git a/e2e/single-cluster/release_names_test.go b/e2e/single-cluster/release_names_test.go
index 5db581fe..af148759 100644
--- a/e2e/single-cluster/release_names_test.go
+++ b/e2e/single-cluster/release_names_test.go
@@ -1,4 +1,4 @@
-package examples_test
+package singlecluster_test
 
 import (
 	"strings"
@@ -10,7 +10,7 @@ import (
 	. "github.com/onsi/gomega"
 )
 
-var _ = Describe("ReleaseName", func() {
+var _ = Describe("Release Name", func() {
 	var (
 		asset string
 		k     kubectl.Command
diff --git a/e2e/single-cluster/single_cluster_test.go b/e2e/single-cluster/single_cluster_test.go
index 05b9c392..d3d69908 100644
--- a/e2e/single-cluster/single_cluster_test.go
+++ b/e2e/single-cluster/single_cluster_test.go
@@ -1,4 +1,4 @@
-package examples_test
+package singlecluster_test
 
 import (
 	"strings"
@@ -10,8 +10,7 @@ import (
 	. "github.com/onsi/gomega"
 )
 
-// These tests use the examples from https://github.com/rancher/fleet-examples/tree/master/single-cluster
-var _ = Describe("Single Cluster Examples", func() {
+var _ = Describe("Single Cluster Deployments", func() {
 	var (
 		asset string
 		k     kubectl.Command
diff --git a/e2e/single-cluster/suite_test.go b/e2e/single-cluster/suite_test.go
index b48b3761..2f40434c 100644
--- a/e2e/single-cluster/suite_test.go
+++ b/e2e/single-cluster/suite_test.go
@@ -1,4 +1,5 @@
-package examples_test
+// Package singlecluster contains e2e tests deploying to a single cluster. The tests use kubectl to apply manifests. Expectations are verified by checking cluster resources. Assets refer to the https://github.com/rancher/fleet-test-data git repo.
+package singlecluster_test
 
 import (
 	"testing"
diff --git a/e2e/single-cluster/values_from_test.go b/e2e/single-cluster/values_from_test.go
new file mode 100644
index 00000000..8d82aa3f
--- /dev/null
+++ b/e2e/single-cluster/values_from_test.go
@@ -0,0 +1,75 @@
+package singlecluster_test
+
+import (
+	"encoding/json"
+
+	"github.com/rancher/fleet/e2e/testenv"
+	"github.com/rancher/fleet/e2e/testenv/kubectl"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+var _ = Describe("ValuesFrom", func() {
+	var (
+		// k is the kubectl command for the cluster registration namespace
+		k kubectl.Command
+		// kw is the kubectl command for namespace the workload is deployed to
+		kw        kubectl.Command
+		namespace string
+	)
+
+	BeforeEach(func() {
+		k = env.Kubectl.Namespace(env.Namespace)
+		namespace = testenv.NewNamespaceName("values-from")
+		kw = k.Namespace(namespace)
+
+		out, err := k.Create("ns", namespace)
+		Expect(err).ToNot(HaveOccurred(), out)
+
+		out, err = k.Namespace(namespace).Create("secret", "generic", "secret-values",
+			"--from-file=values.yaml="+testenv.AssetPath("single-cluster/values-from-secret.yaml"))
+		Expect(err).ToNot(HaveOccurred(), out)
+
+		out, err = k.Namespace("default").Create("configmap", "configmap-values",
+			"--from-file=values.yaml="+testenv.AssetPath("single-cluster/values-from-configmap.yaml"))
+		Expect(err).ToNot(HaveOccurred(), out)
+
+		err = testenv.CreateGitRepo(k, namespace, "values-from", "master", "helm-values-from")
+		Expect(err).ToNot(HaveOccurred())
+
+		DeferCleanup(func() {
+			out, err := k.Delete("gitrepo", "values-from")
+			Expect(err).ToNot(HaveOccurred(), out)
+			out, err = k.Delete("ns", namespace)
+			Expect(err).ToNot(HaveOccurred(), out)
+			out, err = k.Namespace("default").Delete("configmap", "configmap-values")
+			Expect(err).ToNot(HaveOccurred(), out)
+		})
+	})
+
+	When("fleet.yaml makes use of valuesFrom", func() {
+		Context("referencing a secret as well as a configmap", func() {
+			It("all referenced resources are available as values to the chart", func() {
+				Eventually(func() bool {
+					_, err := kw.Get("configmap", "result")
+					return err == nil
+				}).Should(BeTrue())
+
+				out, err := kw.Get("configmap", "result", "-o", "jsonpath={.data}")
+				Expect(err).ToNot(HaveOccurred(), out)
+				result := map[string]string{}
+				err = json.Unmarshal([]byte(out), &result)
+				Expect(err).ToNot(HaveOccurred())
+
+				Expect(result).To(HaveKeyWithValue("name", "secret overrides values from fleet.yaml"))
+				Expect(result).To(HaveKeyWithValue("secret", "xyz secret"))
+				Expect(result).To(HaveKeyWithValue("config", "config option"))
+				Expect(result).To(HaveKeyWithValue("fleetyaml", "from fleet.yaml"))
+				Expect(result).To(HaveKeyWithValue("englishname", "secret override"))
+				Expect(result).To(HaveKeyWithValue("optionconfigmap", "configmap option"))
+				Expect(result).To(HaveKeyWithValue("optionsecret", "secret option"))
+			})
+		})
+	})
+})
diff --git a/e2e/testenv/env.go b/e2e/testenv/env.go
index d490a2de..fc895acc 100644
--- a/e2e/testenv/env.go
+++ b/e2e/testenv/env.go
@@ -16,9 +16,11 @@ const Timeout = 5 * time.Minute
 type Env struct {
 	Kubectl kubectl.Command
 	// Upstream context for cluster containing the fleet controller and local agent
-	Upstream   string
+	Upstream string
+	// Downstream context for fleet-agent cluster
 	Downstream string
-	Namespace  string
+	// Namespace which contains the cluster resource (cluster registration namespace)
+	Namespace string
 }
 
 func New() *Env {
@@ -43,6 +45,9 @@ func (e *Env) getShellEnv() {
 		e.Namespace = val
 	}
 }
+
+// NewNamespaceName returns a name for a namespace that is unique to the test
+// run. e.g. as a targetNamespace for workloads
 func NewNamespaceName(name string) string {
 	rand.Seed(time.Now().UnixNano())
 	p := make([]byte, 12)
diff --git a/e2e/testenv/template.go b/e2e/testenv/template.go
index 5c7d0a5a..0724de47 100644
--- a/e2e/testenv/template.go
+++ b/e2e/testenv/template.go
@@ -1,14 +1,55 @@
 package testenv
 
 import (
+	"fmt"
 	"html/template"
 	"math/rand"
 	"os"
 	"path"
 	"strconv"
 	"strings"
+
+	"github.com/rancher/fleet/e2e/testenv/kubectl"
+	"github.com/rancher/gitjob/e2e/testenv"
 )
 
+const gitrepoTemplate = "gitrepo-template.yaml"
+
+// GitRepoData can be used with the gitrepo-template.yaml asset when no custom
+// GitRepo properties are required. All fields are required.
+type GitRepoData struct {
+	Name            string
+	Branch          string
+	Paths           []string
+	TargetNamespace string
+}
+
+// CreateGitRepo uses the template to create a gitrepo resource. The namespace is the TargetNamespace for the workloads.
+func CreateGitRepo(k kubectl.Command, namespace string, name string, branch string, paths ...string) error {
+	return ApplyTemplate(k, AssetPath(gitrepoTemplate), GitRepoData{
+		TargetNamespace: namespace,
+		Name:            name,
+		Branch:          branch,
+		Paths:           paths,
+	})
+}
+
+// ApplyTemplate templates a file and applies it to the cluster.
+func ApplyTemplate(k kubectl.Command, asset string, data interface{}) error {
+	tmpdir, _ := os.MkdirTemp("", "fleet-")
+	defer os.RemoveAll(tmpdir)
+
+	output := path.Join(tmpdir, RandomFilename(asset))
+	if err := Template(output, testenv.AssetPath(asset), data); err != nil {
+		return err
+	}
+	out, err := k.Apply("-f", output)
+	if err != nil {
+		return fmt.Errorf("%w: %s", err, out)
+	}
+	return nil
+}
+
 // Template loads a gotemplate from a file and writes templated output to
 // another file, preferably in a temp dir
 func Template(output string, tmplPath string, data any) error {
@@ -33,6 +74,7 @@ func Template(output string, tmplPath string, data any) error {
 // RandomName returns a slightly random name, so temporary assets don't conflict
 func RandomFilename(filename string) string {
 	ext := path.Ext(filename)
+	filename = path.Base(filename)
 	r := strconv.Itoa(rand.Intn(99999)) // nolint:gosec // Non-crypto use
-	return strings.TrimSuffix(filename, ext) + r + ext
+	return strings.TrimSuffix(filename, ext) + r + "." + ext
 }
diff --git a/pkg/helmdeployer/deployer_test.go b/pkg/helmdeployer/deployer_test.go
index a0f60f60..f8ace507 100644
--- a/pkg/helmdeployer/deployer_test.go
+++ b/pkg/helmdeployer/deployer_test.go
@@ -32,7 +32,7 @@ func TestValuesFrom(t *testing.T) {
 
 	configMapName := "configmap-name"
 	configMapNamespace := "configmap-namespace"
-	configMapValues, err := processValuesFromObject(configMapName, configMapNamespace, key, nil, &corev1.ConfigMap{
+	configMapValues, err := valuesFromConfigMap(configMapName, configMapNamespace, key, &corev1.ConfigMap{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      configMapName,
 			Namespace: configMapNamespace,
@@ -45,7 +45,7 @@ func TestValuesFrom(t *testing.T) {
 
 	secretName := "secret-name"
 	secretNamespace := "secret-namespace"
-	secretValues, err := processValuesFromObject(secretName, secretNamespace, key, &corev1.Secret{
+	secretValues, err := valuesFromSecret(secretName, secretNamespace, key, &corev1.Secret{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      secretName,
 			Namespace: secretNamespace,
@@ -53,7 +53,7 @@ func TestValuesFrom(t *testing.T) {
 		Data: map[string][]byte{
 			key: []byte(secretPayload),
 		},
-	}, nil)
+	})
 	a.NoError(err)
 
 	totalValues = mergeValues(totalValues, secretValues)