Skip to content

Commit 327323e

Browse files
committed
load secrets/configs from environment while parsing compose model
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 6adefd5 commit 327323e

File tree

5 files changed

+115
-5
lines changed

5 files changed

+115
-5
lines changed

loader/environment.go

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@ import (
2222
"github.com/compose-spec/compose-go/v2/types"
2323
)
2424

25-
// Will update the environment variables for the format {- VAR} (without interpolation)
26-
// This function should resolve context environment vars for include (passed in env_file)
27-
func resolveServicesEnvironment(dict map[string]any, config types.ConfigDetails) {
25+
// ResolveEnvironment update the environment variables for the format {- VAR} (without interpolation)
26+
func ResolveEnvironment(dict map[string]any, environment types.Mapping) {
27+
resolveServicesEnvironment(dict, environment)
28+
resolveSecretsEnvironment(dict, environment)
29+
resolveConfigsEnvironment(dict, environment)
30+
}
31+
32+
func resolveServicesEnvironment(dict map[string]any, environment types.Mapping) {
2833
services, ok := dict["services"].(map[string]any)
2934
if !ok {
3035
return
@@ -45,7 +50,7 @@ func resolveServicesEnvironment(dict map[string]any, config types.ConfigDetails)
4550
if !ok {
4651
continue
4752
}
48-
if found, ok := config.Environment[varEnv]; ok {
53+
if found, ok := environment[varEnv]; ok {
4954
envs = append(envs, fmt.Sprintf("%s=%s", varEnv, found))
5055
} else {
5156
// either does not exist or it was already resolved in interpolation
@@ -57,3 +62,49 @@ func resolveServicesEnvironment(dict map[string]any, config types.ConfigDetails)
5762
}
5863
dict["services"] = services
5964
}
65+
66+
func resolveSecretsEnvironment(dict map[string]any, environment types.Mapping) {
67+
secrets, ok := dict["secrets"].(map[string]any)
68+
if !ok {
69+
return
70+
}
71+
72+
for name, cfg := range secrets {
73+
secret, ok := cfg.(map[string]any)
74+
if !ok {
75+
continue
76+
}
77+
env, ok := secret["environment"].(string)
78+
if !ok {
79+
continue
80+
}
81+
if found, ok := environment[env]; ok {
82+
secret["content"] = found
83+
}
84+
secrets[name] = secret
85+
}
86+
dict["secrets"] = secrets
87+
}
88+
89+
func resolveConfigsEnvironment(dict map[string]any, environment types.Mapping) {
90+
configs, ok := dict["configs"].(map[string]any)
91+
if !ok {
92+
return
93+
}
94+
95+
for name, cfg := range configs {
96+
config, ok := cfg.(map[string]any)
97+
if !ok {
98+
continue
99+
}
100+
env, ok := config["environment"].(string)
101+
if !ok {
102+
continue
103+
}
104+
if found, ok := environment[env]; ok {
105+
config["content"] = found
106+
}
107+
configs[name] = config
108+
}
109+
dict["configs"] = configs
110+
}

loader/full-struct_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ func secrets(workingDir string) map[string]types.SecretConfig {
588588
"secret4": {
589589
Name: "bar",
590590
Environment: "BAR",
591+
Content: "this is a secret",
591592
Extensions: map[string]interface{}{
592593
"x-bar": "baz",
593594
"x-foo": "bar",

loader/loader.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ func loadYamlModel(ctx context.Context, config types.ConfigDetails, opts *Option
407407
return nil, err
408408
}
409409
}
410-
resolveServicesEnvironment(dict, config)
410+
ResolveEnvironment(dict, config.Environment)
411411

412412
return dict, nil
413413
}

loader/loader_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3288,3 +3288,29 @@ services:
32883288
build := p.Services["test"].Build
32893289
assert.DeepEqual(t, build.Entitlements, []string{"network.host", "security.insecure"})
32903290
}
3291+
3292+
func TestLoadSecretEnvironment(t *testing.T) {
3293+
config, err := loadYAMLWithEnv(`
3294+
name: load-secret-environment
3295+
configs:
3296+
config:
3297+
environment: GA
3298+
secrets:
3299+
secret:
3300+
environment: MEU
3301+
`, map[string]string{
3302+
"GA": "BU",
3303+
"MEU": "Shadoks",
3304+
})
3305+
assert.NilError(t, err)
3306+
assert.DeepEqual(t, config.Configs, types.Configs{
3307+
"config": {
3308+
Environment: "GA",
3309+
Content: "BU",
3310+
}})
3311+
assert.DeepEqual(t, config.Secrets, types.Secrets{
3312+
"secret": {
3313+
Environment: "MEU",
3314+
Content: "Shadoks",
3315+
}})
3316+
}

types/types.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,9 +782,41 @@ type ExtendsConfig struct {
782782
// SecretConfig for a secret
783783
type SecretConfig FileObjectConfig
784784

785+
// MarshalYAML makes SecretConfig implement yaml.Marshaller
786+
func (s SecretConfig) MarshalYAML() (interface{}, error) {
787+
// secret content is set while loading model. Never marshall it
788+
s.Content = ""
789+
return FileObjectConfig(s), nil
790+
}
791+
792+
// MarshalJSON makes SecretConfig implement json.Marshaller
793+
func (s SecretConfig) MarshalJSON() ([]byte, error) {
794+
// secret content is set while loading model. Never marshall it
795+
s.Content = ""
796+
return json.Marshal(FileObjectConfig(s))
797+
}
798+
785799
// ConfigObjConfig is the config for the swarm "Config" object
786800
type ConfigObjConfig FileObjectConfig
787801

802+
// MarshalYAML makes ConfigObjConfig implement yaml.Marshaller
803+
func (s ConfigObjConfig) MarshalYAML() (interface{}, error) {
804+
// config content may have been set from environment while loading model. Marshall actual source
805+
if s.Environment != "" {
806+
s.Content = ""
807+
}
808+
return FileObjectConfig(s), nil
809+
}
810+
811+
// MarshalJSON makes ConfigObjConfig implement json.Marshaller
812+
func (s ConfigObjConfig) MarshalJSON() ([]byte, error) {
813+
// config content may have been set from environment while loading model. Marshall actual source
814+
if s.Environment != "" {
815+
s.Content = ""
816+
}
817+
return json.Marshal(FileObjectConfig(s))
818+
}
819+
788820
type IncludeConfig struct {
789821
Path StringList `yaml:"path,omitempty" json:"path,omitempty"`
790822
ProjectDirectory string `yaml:"project_directory,omitempty" json:"project_directory,omitempty"`

0 commit comments

Comments
 (0)