Skip to content

Commit

Permalink
Merge pull request #150 from vshn/fieldRef
Browse files Browse the repository at this point in the history
Add support for "fieldRef" environment variables
  • Loading branch information
mhutter authored Nov 15, 2024
2 parents 406a916 + 98f3ed1 commit 7d6ef91
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 21 deletions.
34 changes: 24 additions & 10 deletions docs/conversion.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,23 @@ spec:
- secretRef:
# `$name(-$refSlug)-env`
name: "myapp-feat-foo-env"
# To reference a value in a Secret you need to use a special syntax in `services.$name.environment`:
# If an environment value starts with a literal '$_ref_:', it is interpreted as a Secret reference.
# Example which would generate the secretRef shown below:
# `DATABASE_PASSWORD=$_ref_:database-credentials-secret:password`
env:
- DATABASE_PASSWORD
# To reference a value in a Secret you need to use a special syntax in `services.$name.environment`:
# If an environment value starts with a literal '$_secretRef_:', it is interpreted as a Secret reference.
# Example which would generate the secretRef shown below:
# `DATABASE_PASSWORD=$_secretRef_:database-credentials-secret:password`
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: database-credentials-secret
key: password
# To reference a pod field, use `$_fieldRef_:` instead
# Example which would generate the fieldRef shown below:
# `MY_POD_IP=$_fieldRef_:status.podIP`
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
# List of the target port values from `services.$name.ports`
ports:
- containerPort: 8000
Expand Down Expand Up @@ -267,16 +274,23 @@ spec:
- secretRef:
# `$name(-$refSlug)-env`
name: "myapp-feat-foo-env"
# To reference a value in a Secret you need to use a special syntax in `services.$name.environment`:
# If an environment value starts with a literal '$_ref_:', it is interpreted as a Secret reference.
# Example which would generate the secretRef shown below:
# `DATABASE_PASSWORD=$_ref_:database-credentials-secret:password`
env:
- DATABASE_PASSWORD
# To reference a value in a Secret you need to use a special syntax in `services.$name.environment`:
# If an environment value starts with a literal '$_secretRef_:', it is interpreted as a Secret reference.
# Example which would generate the secretRef shown below:
# `DATABASE_PASSWORD=$_secretRef_:database-credentials-secret:password`
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: database-credentials-secret
key: password
# To reference a pod field, use `$_fieldRef_:` instead
# Example which would generate the fieldRef shown below:
# `MY_POD_IP=$_fieldRef_:status.podIP`
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
# List of the target port values from `services.$name.ports`
ports:
- containerPort: 8000
Expand Down
10 changes: 7 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,15 @@ func Main(args []string) int {
}
}
env := util.GetEnv()
if _, ok := env["_ref_"]; ok {
logrus.Error("The environment variable '_ref_' must not be defined as it is needed for internal purposes")
return 1
for _, key := range []string{"_ref_", "_secretRef_", "_fieldRef_"} {
if _, ok := env[key]; ok {
logrus.Errorf("The environment variable '%s' must not be defined as it is needed for internal purposes", key)
return 1
}
}
env["_ref_"] = converter.SecretRefMagic
env["_secretRef_"] = converter.SecretRefMagic
env["_fieldRef_"] = converter.FieldRefMagic
configDetails := composeTypes.ConfigDetails{
ConfigFiles: composeConfigFiles,
Environment: env,
Expand Down
28 changes: 23 additions & 5 deletions pkg/converter/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ import (
)

var (
SecretRefMagic = "ylkBUFN0o29yr4yLCTUZqzgIT6qCIbyj" // magic string to indicate that what follows isn't a value but a reference to a secret
// magic string to indicate that what follows isn't a value but a reference to a secret
SecretRefMagic = "ylkBUFN0o29yr4yLCTUZqzgIT6qCIbyj"

// magic string to indicate that what follows isn't a value but a fieldRef
FieldRefMagic = "VtF2ZSrJBKSEJCiUVkGCyUawAfGBCwou"
)

func composeServiceVolumesToK8s(
Expand Down Expand Up @@ -121,11 +125,17 @@ func composeServicePortsToK8sContainerPorts(workload *ir.Service) []core.Contain
return containerPorts
}

func isReference(value *string) bool {
return value != nil && (strings.HasPrefix(*value, SecretRefMagic+":") || strings.HasPrefix(*value, FieldRefMagic+":"))
}

func composeServiceToSecret(workload *ir.Service, refSlug string, labels map[string]string) *core.Secret {
stringData := make(map[string]string)
for key, value := range workload.AsCompose().Environment {
if value != nil && strings.HasPrefix(*value, SecretRefMagic+":") {
// we've encountered a reference to another secret (starting with "$_ref_:" in the compose file), ignore
if isReference(value) {
// we've encountered a reference to another secret or a field ref
// (starting with "$_secretRef_:" or "$_fieldRef_:" in the compose file),
// ignore
continue
}
if value == nil {
Expand Down Expand Up @@ -365,14 +375,22 @@ func composeServiceToContainer(
for _, key := range keys {
value := workload.AsCompose().Environment[key]
if value != nil && strings.HasPrefix(*value, SecretRefMagic+":") {
// we've encountered a reference to another secret (starting with "$_ref_:" in the compose file)
// we've encountered a reference to another secret (starting with "$_secretRef_:" in the compose file)
refValue := (*value)[len(SecretRefMagic)+1:]
refStrings := strings.SplitN(refValue, ":", 2)
if len(refStrings) != 2 {
logrus.Warnf("Secret reference '$_ref_:%s' has invalid format, should be '$_ref_:SECRETNAME:KEY'. Ignoring.", refValue)
logrus.Warnf("Secret reference '$_secretRef_:%s' has invalid format, should be '$_secretRef_:SECRETNAME:KEY'. Ignoring.", refValue)
continue
}
env = append(env, core.EnvVar{Name: key, ValueFrom: &core.EnvVarSource{SecretKeyRef: &core.SecretKeySelector{LocalObjectReference: core.LocalObjectReference{Name: refStrings[0]}, Key: refStrings[1]}}})
} else if value != nil && strings.HasPrefix(*value, FieldRefMagic+":") {
// we've encountered a fieldRef
refValue := (*value)[len(FieldRefMagic)+1:]
if strings.Contains(refValue, ":") {
logrus.Warnf("FieldRef '$_fieldRef_:%s' has invalid format, should be '$_fieldRef_:PATH'. Ignoring.", refValue)
continue
}
env = append(env, core.EnvVar{Name: key, ValueFrom: &core.EnvVarSource{FieldRef: &core.ObjectFieldSelector{FieldPath: refValue}}})
}
}

Expand Down
7 changes: 4 additions & 3 deletions tests/golden/env-vars/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ services:
- FOO
- BAR=${BAR}
- something_else=${BAZ}
- "PASSWORD=$_ref_:mongodb-secret:password"
- "FOOREF=$_ref_:foo:fooooooo"
- "BARREF=$_ref_:bar:baaaaaar"
- "PASSWORD=$_secretRef_:mongodb-secret:password"
- "FOOREF=$_secretRef_:foo:fooooooo"
- "BARREF=$_secretRef_:bar:baaaaaar"
- "MY_IP=$_fieldRef_:status.podIP"
4 changes: 4 additions & 0 deletions tests/golden/env-vars/manifests/fooBar-oasp-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ spec:
secretKeyRef:
key: fooooooo
name: foo
- name: MY_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: PASSWORD
valueFrom:
secretKeyRef:
Expand Down

0 comments on commit 7d6ef91

Please sign in to comment.