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

Allow : in --data-values-file path #609

Merged
merged 10 commits into from
Mar 30, 2022
53 changes: 45 additions & 8 deletions pkg/cmd/template/cmd_data_values_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package template_test

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -183,39 +184,58 @@ func TestDataValuesWithLibraryAttachedFlags(t *testing.T) {
tplBytes := []byte(`
#@ load("@ytt:library", "library")
#@ load("@ytt:template", "template")
#@ load("@ytt:data", "data")

root: #@ data.values
--- #@ template.replace(library.get("lib", alias="inst1").eval())`)

libTplBytes := []byte(`
#@ load("@ytt:library", "library")
#@ load("@ytt:template", "template")
#@ load("@ytt:data", "data")

lib-val: #@ data.values.lib_val
from_library: #@ data.values
--- #@ template.replace(library.get("nested-lib").eval())
`)

libValuesBytes := []byte(`
#@data/values
---
lib_val: override-me
val0: override-me
`)

nestedLibTplBytes := []byte(`
#@ load("@ytt:data", "data")

nested-lib-val: #@ data.values.nested_lib_val
from_nested_lib: #@ data.values
`)

nestedLibValuesBytes := []byte(`
#@data/values
---
nested_lib_val: override-me
val1: override-me
`)

expectedYAMLTplData := `lib-val: test
dvs2 := []byte(`val2: 2`)

dvs3 := []byte(`val3: 3`)

dvs4 := []byte(`val4: 4`)

dvs6 := []byte(`6`)

expectedYAMLTplData := `root:
val2: 2
---
nested-lib-val: passes
from_library:
val0: 0
val3: 3
val4: 4
val5: "5"
val6: "6"
---
from_nested_lib:
val1: 1
`

filesToProcess := files.NewSortedFiles([]*files.File{
Expand All @@ -230,8 +250,25 @@ nested-lib-val: passes
opts := cmdtpl.NewOptions()

opts.DataValuesFlags = cmdtpl.DataValuesFlags{
// TODO env and files?
KVsFromYAML: []string{"@~inst1:lib_val=test", "@~inst1@nested-lib:nested_lib_val=passes"},
KVsFromYAML: []string{"@~inst1:val0=0", "@~inst1@nested-lib:val1=1"},
FromFiles: []string{"c:\\User\\user\\dvs2.yml", "@~inst1:dvs3.yml", "@lib:D:\\User\\user\\dvs4.yml"},
EnvFromStrings: []string{"@lib:DVS"},
EnvironFunc: func() []string { return []string{"DVS_val5=5"} },
KVsFromFiles: []string{"@lib:val6=c:\\User\\user\\dvs6.yml"},
ReadFileFunc: func(path string) ([]byte, error) {
switch path {
case "c:\\User\\user\\dvs2.yml":
return dvs2, nil
case "dvs3.yml":
return dvs3, nil
case "D:\\User\\user\\dvs4.yml":
return dvs4, nil
case "c:\\User\\user\\dvs6.yml":
return dvs6, nil
default:
return nil, fmt.Errorf("Unknown file '%s'", path)
}
},
}

out := opts.RunWithFiles(cmdtpl.Input{Files: filesToProcess}, ui)
Expand Down
57 changes: 33 additions & 24 deletions pkg/cmd/template/data_values_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import (
"github.com/vmware-tanzu/carvel-ytt/pkg/files"
"github.com/vmware-tanzu/carvel-ytt/pkg/template"
"github.com/vmware-tanzu/carvel-ytt/pkg/workspace/datavalues"
"github.com/vmware-tanzu/carvel-ytt/pkg/workspace/ref"
"github.com/vmware-tanzu/carvel-ytt/pkg/yamlmeta"
yttoverlay "github.com/vmware-tanzu/carvel-ytt/pkg/yttlibrary/overlay"
)

const (
dvsKVSep = "="
dvsMapKeySep = "."
dvsKVSep = "="
dvsMapKeySep = "."
libraryKeySep = ":"
)

type DataValuesFlags struct {
Expand Down Expand Up @@ -135,15 +137,15 @@ func (s *DataValuesFlags) AsOverlays(strict bool) ([]*datavalues.Envelope, []*da
return overlayValues, libraryOverlays, nil
}

func (s *DataValuesFlags) file(path string, strict bool) ([]*datavalues.Envelope, error) {
libRef, path, err := s.libraryRefAndKey(path)
func (s *DataValuesFlags) file(fullPath string, strict bool) ([]*datavalues.Envelope, error) {
libRef, path, err := s.libraryRefAndKey(fullPath)
if err != nil {
return nil, err
}

contents, err := s.readFile(path)
if err != nil {
return nil, fmt.Errorf("Reading file '%s': %s", path, err)
return nil, fmt.Errorf("Unable to read file '%s' from flag value '%s': %s", path, err)
cari-lynn marked this conversation as resolved.
Show resolved Hide resolved
}

docSetOpts := yamlmeta.DocSetOpts{
Expand Down Expand Up @@ -188,7 +190,7 @@ func (s *DataValuesFlags) env(prefix string, src dataValuesFlagsSource) ([]*data
envVars = s.EnvironFunc()
}

libRef, keyPrefix, err := s.libraryRefAndKey(prefix)
libRef, keyPrefix, err := s.libraryRefAndKeyStrict(prefix)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -235,7 +237,7 @@ func (s *DataValuesFlags) kv(kv string, src dataValuesFlagsSource) (*datavalues.
return nil, fmt.Errorf("Deserializing value for key '%s': %s", pieces[0], err)
}

libRef, key, err := s.libraryRefAndKey(pieces[0])
libRef, key, err := s.libraryRefAndKeyStrict(pieces[0])
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -273,27 +275,34 @@ func (s *DataValuesFlags) kvFile(kv string) (*datavalues.Envelope, error) {

return datavalues.NewEnvelopeWithLibRef(overlay, libRef)
}
func (DataValuesFlags) libraryRefAndKeyStrict(key string) (string, string, error) {
libRef, key, err := DataValuesFlags{}.libraryRefAndKey(key)
if err != nil {
return "", "", err
}
if len(strings.Split(key, libraryKeySep)) > 1 {
// error on a common syntax mistake
return "", "", fmt.Errorf("Expected at most one library-key separator '%s' in '%s'", libraryKeySep, key)
}
return libRef, key, nil
}

// libraryRefAndKey separates a library reference and a key.
// A library reference starts with ref.LibrarySep, and ends with the first occurrence of libraryKeySep.
func (DataValuesFlags) libraryRefAndKey(key string) (string, string, error) {
const (
libraryKeySep = ":"
)

keyPieces := strings.Split(key, libraryKeySep)

switch len(keyPieces) {
case 1:
return "", key, nil

case 2:
if len(keyPieces[0]) == 0 {
return "", "", fmt.Errorf("Expected library ref to not be empty")
if strings.HasPrefix(key, ref.LibrarySep) {
keyPieces := strings.SplitN(key, libraryKeySep, 2)
switch len(keyPieces) {
case 1:
return "", key, nil
case 2:
if len(keyPieces[0]) == 1 {
return "", "", fmt.Errorf("Expected library ref to not be empty")
}
return keyPieces[0], keyPieces[1], nil
}
return keyPieces[0], keyPieces[1], nil

default:
return "", "", fmt.Errorf("Expected at most one library-key separator '%s' in '%s'", libraryKeySep, key)
}
return "", key, nil
}

func (s *DataValuesFlags) buildOverlay(keyPieces []string, value interface{}, desc string, line string) *yamlmeta.Document {
Expand Down