Skip to content

Commit

Permalink
limayaml: add a check to verify whether the variables defined in `par…
Browse files Browse the repository at this point in the history
…am` are actually used

This check needs to be performed before the template is expanded, so it should be added before calling `FillDefault()`.

Signed-off-by: Norio Nomura <[email protected]>
  • Loading branch information
norio-nomura committed Jul 25, 2024
1 parent 3f5501b commit 762d46a
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
5 changes: 5 additions & 0 deletions pkg/limayaml/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ func Load(b []byte, filePath string) (*LimaYAML, error) {
return nil, err
}

// It should be called before the `y` parameter is passed to FillDefault() that execute template.
if err := ValidateParamIsUsed(&y); err != nil {
return nil, err
}

FillDefault(&y, &d, &o, filePath)
return &y, nil
}
45 changes: 43 additions & 2 deletions pkg/limayaml/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"runtime"
"strings"

Expand Down Expand Up @@ -252,7 +253,7 @@ func Validate(y *LimaYAML, warn bool) error {
}
if rule.GuestSocket != "" {
if !path.IsAbs(rule.GuestSocket) {
return fmt.Errorf("field `%s.guestSocket` must be an absolute path", field)
return fmt.Errorf("field `%s.guestSocket` must be an absolute path, but is %q", field, rule.GuestSocket)
}
if rule.HostSocket == "" && rule.HostPortRange[1]-rule.HostPortRange[0] > 0 {
return fmt.Errorf("field `%s.guestSocket` can only be mapped to a single port or socket. not a range", field)
Expand Down Expand Up @@ -287,7 +288,7 @@ func Validate(y *LimaYAML, warn bool) error {
field := fmt.Sprintf("CopyToHost[%d]", i)
if rule.GuestFile != "" {
if !path.IsAbs(rule.GuestFile) {
return fmt.Errorf("field `%s.guest` must be an absolute path", field)
return fmt.Errorf("field `%s.guest` must be an absolute path, but is %q", field, rule.GuestFile)
}
}
if rule.HostFile != "" {
Expand Down Expand Up @@ -385,6 +386,46 @@ func validateNetwork(y *LimaYAML) error {
return nil
}

// ValidateParamIsUsed checks if the keys in the `param` field are used in any script, probe, copyToHost, or portForward.
// It should be called before the `y` parameter is passed to FillDefault() that execute template.
func ValidateParamIsUsed(y *LimaYAML) error {
for key := range y.Param {
re, err := regexp.Compile(`{{[^}]*\.Param\.` + key + `[^}]*}}`)
if err != nil {
return fmt.Errorf("field to compile regexp for key %q: %w", key, err)
}
keyIsUsed := false
for _, p := range y.Provision {
if re.MatchString(p.Script) {
keyIsUsed = true
break
}
}
for _, p := range y.Probes {
if re.MatchString(p.Script) {
keyIsUsed = true
break
}
}
for _, p := range y.CopyToHost {
if re.MatchString(p.GuestFile) || re.MatchString(p.HostFile) {
keyIsUsed = true
break
}
}
for _, p := range y.PortForwards {
if re.MatchString(p.GuestSocket) || re.MatchString(p.HostSocket) {
keyIsUsed = true
break
}
}
if !keyIsUsed {
return fmt.Errorf("field `param` key %q is not used in any provision, probe, copyToHost, or portForward", key)
}
}
return nil
}

func validatePort(field string, port int) error {
switch {
case port < 0:
Expand Down
21 changes: 21 additions & 0 deletions pkg/limayaml/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,24 @@ func TestValidateDefault(t *testing.T) {
err = Validate(y, true)
assert.NilError(t, err)
}

func TestValidateParamIsUsed(t *testing.T) {
paramYaml := `param:
name: value`
_, err := Load([]byte(paramYaml), "paramIsNotUsed.yaml")
assert.Error(t, err, "field `param` key \"name\" is not used in any provision, probe, copyToHost, or portForward")

fieldsUsingParam := []string{
`provision: [{"script": "echo {{ .Param.name }}"}]`,
`probes: [{"script": "echo {{ .Param.name }}"}]`,
`copyToHost: [{"guest": "/tmp/{{ .Param.name }}", "host": "/tmp"}]`,
`copyToHost: [{"guest": "/tmp", "host": "/tmp/{{ .Param.name }}"}]`,
`portForwards: [{"guestSocket": "/tmp/{{ .Param.name }}", "hostSocket": "/tmp"}]`,
`portForwards: [{"guestSocket": "/tmp", "hostSocket": "/tmp/{{ .Param.name }}"}]`,
}
for _, fieldUsingParam := range fieldsUsingParam {
_, err = Load([]byte(fieldUsingParam+"\n"+paramYaml), "paramIsUsed.yaml")
//
assert.NilError(t, err)
}
}

0 comments on commit 762d46a

Please sign in to comment.