1
0
mirror of https://github.com/rancher/types.git synced 2025-08-01 21:07:41 +00:00

Fix env variable interpolation

- Add new type EnvironmentVar to emulate k8s' EnvVar type structure with
an EnvironmentFrom nested type (EnvironmentFrom represents everything
relevant in k8s' EnvVarSource type)
- Modify env mapper to store environmental variables in an array of
EnvironmentVar types to preserve their order (variables of type EnvFromSource
are still kept separate like upstream).
This commit is contained in:
Steven Crespo 2020-12-25 22:19:49 -08:00
parent 72359190db
commit 7d11888f1e
3 changed files with 143 additions and 124 deletions

View File

@ -582,7 +582,7 @@ func podTypes(schemas *types.Schemas) *types.Schemas {
MustImport(&Version, v1.Handler{}, handlerOverride{}).
MustImport(&Version, v1.Probe{}, handlerOverride{}).
MustImport(&Version, v1.Container{}, struct {
Environment map[string]string
Environment []EnvironmentVar
EnvironmentFrom []EnvironmentFrom
InitContainer bool
State string

View File

@ -37,6 +37,12 @@ type handlerOverride struct {
TCP bool
}
type EnvironmentVar struct {
Name string
Value string
ValueFrom *EnvironmentFrom
}
type EnvironmentFrom struct {
Source string `norman:"type=enum,options=field|resource|configMap|secret"`
SourceName string

View File

@ -1,11 +1,9 @@
package mapper
import (
"sort"
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/convert"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
)
type EnvironmentMapper struct {
@ -14,71 +12,82 @@ type EnvironmentMapper struct {
func (e EnvironmentMapper) FromInternal(data map[string]interface{}) {
var env []v1.EnvVar
var envFrom []v1.EnvFromSource
envMap := map[string]interface{}{}
var envFromMaps []interface{}
var environment, environmentFrom []interface{}
if err := convert.ToObj(data["env"], &env); err == nil {
for _, envVar := range env {
if envVar.ValueFrom == nil {
envMap[envVar.Name] = envVar.Value
environment = append(environment, map[string]interface{}{
"name": envVar.Name,
"value": envVar.Value,
})
continue
}
if envVar.ValueFrom.FieldRef != nil {
envFromMaps = append(envFromMaps, map[string]interface{}{
"source": "field",
"sourceName": envVar.ValueFrom.FieldRef.FieldPath,
"targetKey": envVar.Name,
environment = append(environment, map[string]interface{}{
"name": envVar.Name,
"valueFrom": map[string]interface{}{
"source": "field",
"sourceName": envVar.ValueFrom.FieldRef.FieldPath,
"targetKey": envVar.Name,
},
})
}
if envVar.ValueFrom.ResourceFieldRef != nil {
envFromMaps = append(envFromMaps, map[string]interface{}{
"source": "resource",
"sourceName": envVar.ValueFrom.ResourceFieldRef.ContainerName,
"sourceKey": envVar.ValueFrom.ResourceFieldRef.Resource,
"divisor": envVar.ValueFrom.ResourceFieldRef.Divisor,
"targetKey": envVar.Name,
environment = append(environment, map[string]interface{}{
"name": envVar.Name,
"valueFrom": map[string]interface{}{
"source": "resource",
"sourceName": envVar.ValueFrom.ResourceFieldRef.ContainerName,
"sourceKey": envVar.ValueFrom.ResourceFieldRef.Resource,
"divisor": envVar.ValueFrom.ResourceFieldRef.Divisor,
"targetKey": envVar.Name,
},
})
}
if envVar.ValueFrom.ConfigMapKeyRef != nil {
envFromMaps = append(envFromMaps, map[string]interface{}{
"source": "configMap",
"sourceName": envVar.ValueFrom.ConfigMapKeyRef.Name,
"sourceKey": envVar.ValueFrom.ConfigMapKeyRef.Key,
"optional": getValue(envVar.ValueFrom.ConfigMapKeyRef.Optional),
"targetKey": envVar.Name,
environment = append(environment, map[string]interface{}{
"name": envVar.Name,
"valueFrom": map[string]interface{}{
"source": "configMap",
"sourceName": envVar.ValueFrom.ConfigMapKeyRef.Name,
"sourceKey": envVar.ValueFrom.ConfigMapKeyRef.Key,
"optional": getValue(envVar.ValueFrom.ConfigMapKeyRef.Optional),
"targetKey": envVar.Name,
},
})
}
if envVar.ValueFrom.SecretKeyRef != nil {
envFromMaps = append(envFromMaps, map[string]interface{}{
"source": "secret",
"sourceName": envVar.ValueFrom.SecretKeyRef.Name,
"sourceKey": envVar.ValueFrom.SecretKeyRef.Key,
"optional": getValue(envVar.ValueFrom.SecretKeyRef.Optional),
"targetKey": envVar.Name,
environment = append(environment, map[string]interface{}{
"name": envVar.Name,
"valueFrom": map[string]interface{}{
"source": "secret",
"sourceName": envVar.ValueFrom.SecretKeyRef.Name,
"sourceKey": envVar.ValueFrom.SecretKeyRef.Key,
"optional": getValue(envVar.ValueFrom.SecretKeyRef.Optional),
"targetKey": envVar.Name,
},
})
}
}
}
if err := convert.ToObj(data["envFrom"], &envFrom); err == nil {
for _, envVar := range envFrom {
if envVar.SecretRef != nil {
envFromMaps = append(envFromMaps, map[string]interface{}{
for _, envFromSource := range envFrom {
if envFromSource.SecretRef != nil {
environmentFrom = append(environmentFrom, map[string]interface{}{
"source": "secret",
"sourceName": envVar.SecretRef.Name,
"prefix": envVar.Prefix,
"optional": getValue(envVar.SecretRef.Optional),
"sourceName": envFromSource.SecretRef.Name,
"prefix": envFromSource.Prefix,
"optional": getValue(envFromSource.SecretRef.Optional),
"type": "/v3/project/schemas/environmentFrom",
})
}
if envVar.ConfigMapRef != nil {
envFromMaps = append(envFromMaps, map[string]interface{}{
if envFromSource.ConfigMapRef != nil {
environmentFrom = append(environmentFrom, map[string]interface{}{
"source": "configMap",
"sourceName": envVar.ConfigMapRef.Name,
"prefix": envVar.Prefix,
"optional": getValue(envVar.ConfigMapRef.Optional),
"sourceName": envFromSource.ConfigMapRef.Name,
"prefix": envFromSource.Prefix,
"optional": getValue(envFromSource.ConfigMapRef.Optional),
"type": "/v3/project/schemas/environmentFrom",
})
}
@ -88,103 +97,107 @@ func (e EnvironmentMapper) FromInternal(data map[string]interface{}) {
delete(data, "env")
delete(data, "envFrom")
if len(envMap) > 0 {
data["environment"] = envMap
if len(environment) > 0 {
data["environment"] = environment
}
if len(envFromMaps) > 0 {
data["environmentFrom"] = envFromMaps
if len(environmentFrom) > 0 {
data["environmentFrom"] = environmentFrom
}
}
func (e EnvironmentMapper) ToInternal(data map[string]interface{}) error {
var envVar []map[string]interface{}
var envVarFrom []map[string]interface{}
var environment, env, envFrom []map[string]interface{}
var valueFrom map[string]interface{}
var orderedKeys []string
environment := convert.ToMapInterface(data["environment"])
for k := range environment {
orderedKeys = append(orderedKeys, k)
if err := convert.ToObj(data["environment"], &environment); err == nil {
for _, environmentVar := range environment {
if convert.ToString(environmentVar["value"]) != "" {
env = append(env, map[string]interface{}{
"name": environmentVar["name"],
"value": environmentVar["value"],
})
continue
}
if err = convert.ToObj(environmentVar["valueFrom"], &valueFrom); err == nil {
source := convert.ToString(valueFrom["source"])
if source == "" {
continue
}
targetKey := convert.ToString(valueFrom["targetKey"])
sourceKey := convert.ToString(valueFrom["sourceKey"])
if targetKey == "" {
targetKey = sourceKey
}
switch source {
case "field":
env = append(env, map[string]interface{}{
"name": targetKey,
"valueFrom": map[string]interface{}{
"fieldRef": map[string]interface{}{
"fieldPath": valueFrom["sourceName"],
},
},
})
case "resource":
env = append(env, map[string]interface{}{
"name": targetKey,
"valueFrom": map[string]interface{}{
"resourceFieldRef": map[string]interface{}{
"containerName": valueFrom["sourceName"],
"resource": valueFrom["sourceKey"],
"divisor": valueFrom["divisor"],
},
},
})
case "configMap":
env = append(env, map[string]interface{}{
"name": targetKey,
"valueFrom": map[string]interface{}{
"configMapKeyRef": map[string]interface{}{
"name": valueFrom["sourceName"],
"key": valueFrom["sourceKey"],
"optional": valueFrom["optional"],
},
},
})
case "secret":
env = append(env, map[string]interface{}{
"name": targetKey,
"valueFrom": map[string]interface{}{
"secretKeyRef": map[string]interface{}{
"name": valueFrom["sourceName"],
"key": valueFrom["sourceKey"],
"optional": valueFrom["optional"],
},
},
})
}
}
}
}
sort.Strings(orderedKeys)
for _, key := range orderedKeys {
envVar = append(envVar, map[string]interface{}{
"name": key,
"value": environment[key],
})
}
for _, value := range convert.ToMapSlice(data["environmentFrom"]) {
source := convert.ToString(value["source"])
for _, environmentFrom := range convert.ToMapSlice(data["environmentFrom"]) {
source := convert.ToString(environmentFrom["source"])
if source == "" {
continue
}
targetKey := convert.ToString(value["targetKey"])
sourceKey := convert.ToString(value["sourceKey"])
targetKey := convert.ToString(environmentFrom["targetKey"])
sourceKey := convert.ToString(environmentFrom["sourceKey"])
if targetKey == "" && sourceKey == "" {
switch source {
case "secret":
envVarFrom = append(envVarFrom, map[string]interface{}{
"prefix": value["prefix"],
envFrom = append(envFrom, map[string]interface{}{
"prefix": environmentFrom["prefix"],
"secretRef": map[string]interface{}{
"name": value["sourceName"],
"optional": value["optional"],
"name": environmentFrom["sourceName"],
"optional": environmentFrom["optional"],
},
})
case "configMap":
envVarFrom = append(envVarFrom, map[string]interface{}{
"prefix": value["prefix"],
envFrom = append(envFrom, map[string]interface{}{
"prefix": environmentFrom["prefix"],
"configMapRef": map[string]interface{}{
"name": value["sourceName"],
"optional": value["optional"],
},
})
}
} else {
if targetKey == "" {
targetKey = sourceKey
}
switch source {
case "field":
envVar = append(envVar, map[string]interface{}{
"name": targetKey,
"valueFrom": map[string]interface{}{
"fieldRef": map[string]interface{}{
"fieldPath": value["sourceName"],
},
},
})
case "resource":
envVar = append(envVar, map[string]interface{}{
"name": targetKey,
"valueFrom": map[string]interface{}{
"resourceFieldRef": map[string]interface{}{
"containerName": value["sourceName"],
"resource": value["sourceKey"],
"divisor": value["divisor"],
},
},
})
case "configMap":
envVar = append(envVar, map[string]interface{}{
"name": targetKey,
"valueFrom": map[string]interface{}{
"configMapKeyRef": map[string]interface{}{
"name": value["sourceName"],
"key": value["sourceKey"],
"optional": value["optional"],
},
},
})
case "secret":
envVar = append(envVar, map[string]interface{}{
"name": targetKey,
"valueFrom": map[string]interface{}{
"secretKeyRef": map[string]interface{}{
"name": value["sourceName"],
"key": value["sourceKey"],
"optional": value["optional"],
},
"name": environmentFrom["sourceName"],
"optional": environmentFrom["optional"],
},
})
}
@ -193,8 +206,8 @@ func (e EnvironmentMapper) ToInternal(data map[string]interface{}) error {
delete(data, "environment")
delete(data, "environmentFrom")
data["env"] = envVar
data["envFrom"] = envVarFrom
data["env"] = env
data["envFrom"] = envFrom
return nil
}