Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

Commit

Permalink
enhance: allow dots in env vars (#2428)
Browse files Browse the repository at this point in the history
Do not ignore environment variables with dots in the key defined in the Acornfile, e.g. `env: "foo.bar": "baz"`
  • Loading branch information
iwilltry42 authored Jan 18, 2024
1 parent 7632a3e commit 3cf6c10
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
4 changes: 2 additions & 2 deletions pkg/apis/internal.acorn.io/v1/unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -1156,7 +1156,7 @@ func (in *EnvVars) UnmarshalJSON(data []byte) error {
if ok {
v.Secret = sec.SecretReference
} else {
v.Name = k
v.Name = strings.ReplaceAll(k, ".", "\\.") // escape dots so they don't interfere with name separator '.' during interpolation
}
*in = append(*in, (EnvVar)(v))
}
Expand Down Expand Up @@ -1396,7 +1396,7 @@ func parseEnvVar(key, value string) (result EnvVar, _ error) {
return result, nil
}

result.Name = key
result.Name = strings.ReplaceAll(key, ".", "\\.") // escape dots so they don't interfere with name separator '.' during interpolation

sec, ok, err = parseSecretReference(value)
if err != nil {
Expand Down
15 changes: 9 additions & 6 deletions pkg/controller/appdefinition/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@ func toEnv(envs []v1.EnvVar, appEnvs []v1.NameValue, interpolator *secrets.Inter
if appEnvNames.Has(env.Name) {
continue
}
interpolated, ok := interpolator.ToEnv(env.Name, env.Value)
if ok {
interpolated, noDotInKey := interpolator.ToEnv(env.Name, env.Value)
if noDotInKey {
interpolated.Name = strings.ReplaceAll(interpolated.Name, "\\.", ".") // restore dots that were escaped during unmarshalling
result = append(result, interpolated)
}
} else {
Expand All @@ -177,8 +178,9 @@ func toEnv(envs []v1.EnvVar, appEnvs []v1.NameValue, interpolator *secrets.Inter
continue
}
if strings.Contains(env.Secret.Name, ".") {
interpolated, ok := interpolator.ToEnv(env.Name, fmt.Sprintf("@{secrets.%s.%s}", env.Secret.Name, env.Secret.Key))
if ok {
interpolated, noDotInKey := interpolator.ToEnv(env.Name, fmt.Sprintf("@{secrets.%s.%s}", env.Secret.Name, env.Secret.Key))
if noDotInKey {
interpolated.Name = strings.ReplaceAll(interpolated.Name, "\\.", ".") // restore dots that were escaped during unmarshalling
result = append(result, interpolated)
}
} else {
Expand All @@ -197,8 +199,9 @@ func toEnv(envs []v1.EnvVar, appEnvs []v1.NameValue, interpolator *secrets.Inter
}
}
for _, appEnv := range appEnvs {
interpolated, ok := interpolator.ToEnv(appEnv.Name, appEnv.Value)
if ok {
interpolated, noDotInKey := interpolator.ToEnv(appEnv.Name, appEnv.Value)
if noDotInKey {
interpolated.Name = strings.ReplaceAll(interpolated.Name, "\\.", ".") // restore dots that were escaped during unmarshalling
result = append(result, interpolated)
}
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/controller/appdefinition/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ func TestEnvironment(t *testing.T) {
{
Name: "foo",
},
{
Name: "foo\\.bar",
Value: "baz",
},
},
},
},
Expand All @@ -142,6 +146,10 @@ func TestEnvironment(t *testing.T) {
Name: "foo",
Value: "",
},
{
Name: "foo.bar",
Value: "baz",
},
}, dep.Spec.Template.Spec.Containers[0].Env)
}

Expand Down
21 changes: 17 additions & 4 deletions pkg/secrets/interpolation.go
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,19 @@ func (i *Interpolator) getContainerOrJobName() string {
return i.jobName
}

// hasUnescapedDot checks if a string contains an unescaped dot (i.e., a dot not escaped by a backslash).
func hasUnescapedDot(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] == '.' {
// Match if it's the first character or not escaped by a backslash
if i == 0 || s[i-1] != '\\' {
return true
}
}
}
return false
}

func (i *Interpolator) ToEnv(key, value string) (corev1.EnvVar, bool) {
prefix := i.getContainerOrJobName()
key = strings.TrimPrefix(key, prefix+".")
Expand All @@ -571,7 +584,7 @@ func (i *Interpolator) ToEnv(key, value string) (corev1.EnvVar, bool) {
return corev1.EnvVar{
Name: key,
Value: value,
}, !strings.Contains(key, ".")
}, !hasUnescapedDot(key)
}

newValue, err := i.Replace(value)
Expand All @@ -580,13 +593,13 @@ func (i *Interpolator) ToEnv(key, value string) (corev1.EnvVar, bool) {
return corev1.EnvVar{
Name: newKey,
Value: value,
}, !strings.Contains(key, ".")
}, !hasUnescapedDot(key)
}
if value == newValue {
return corev1.EnvVar{
Name: newKey,
Value: value,
}, !strings.Contains(newKey, ".")
}, !hasUnescapedDot(newKey)
}

return corev1.EnvVar{
Expand All @@ -599,7 +612,7 @@ func (i *Interpolator) ToEnv(key, value string) (corev1.EnvVar, bool) {
Key: i.addContent(newValue),
},
},
}, !strings.Contains(newKey, ".")
}, !hasUnescapedDot(newKey)
}

func (i *Interpolator) Objects() []kclient.Object {
Expand Down

0 comments on commit 3cf6c10

Please sign in to comment.