Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for merging multiple config files from variable #43

Merged
merged 7 commits into from
Jan 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ name: goreleaser

on:
push:
branches:
- "!*"
tags:
- "v*"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
vars:
namespace: eg

override_with_empty: [1]
override_with_ints: [1]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import:
- globals

vars:
region: us-east-2
environment: ue2

override_with_empty: []
override_with_ints: [2]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import:
- ue2-globals

vars:
stage: prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import:
- ue3-globals

vars:
stage: prod
48 changes: 48 additions & 0 deletions examples/advanced/dynamic-config-inheritance/main.variant
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
option "config-dir" {
type = string
}

job "stack config" {
concurrency = 1
description = "Generate stack config in YAML format"

option "stack" {
type = string
description = "Stack"
short = "s"
}

variable "configs" {
value = flatten(concat([
# 1st level of imports
for k1, imports1 in yamldecode(file(format("%s/%s.yaml", opt.config-dir, opt.stack))): [
for import1 in imports1: concat([
# 1st level import's imports = 2nd level of imports
for k2, imports2 in yamldecode(file(format("%s/%s.yaml", opt.config-dir, import1))): [
for import2 in imports2: [
# 2nd level import's imports = 3rd level of imports
format("%s/%s.yaml", opt.config-dir, import2)
]
] if k2 == "import"
], [
format("%s/%s.yaml", opt.config-dir, import1)
])
] if k1 == "import"
], [
format("%s/%s.yaml", opt.config-dir, opt.stack)
]))
}

config "all" {
source file {
paths = var.configs
}
}

exec {
command = "echo"
args = [
jsonencode(conf.all)
]
}
}
165 changes: 165 additions & 0 deletions examples/advanced/dynamic-config-inheritance/main_test.variant
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
test "stack config" {
case "ue2-prod" {
stack = "ue2-prod"
exitstatus = 0
err = ""
namespace = "eg"
region = "us-east-2"
environment = "ue2"
stage = "prod"
override_with_empty = []
override_with_ints = [2]
}

// missing stack config
case "ue1-prod" {
stack = "ue1-prod"
exitstatus = 1
err = trimspace(<<EOS
job "stack config": ${abspath("main.variant")}:18,43-50: Invalid function argument; Invalid value for "path" parameter: no file exists at config/ue1-prod.yaml; this function works only with files that are distributed as part of the configuration source code, so if this file will be created by a resource in this configuration you must instead obtain this result from an attribute of that resource.
EOS
)
namespace = "UNDEFINED"
region = "UNDEFINED"
environment = "UNDEFINED"
stage = "UNDEFINED"
override_with_empty = "UNDEFINED"
override_with_ints = "UNDEFINED"
}

// missing stack config import
case "ue3-prod" {
stack = "ue3-prod"
exitstatus = 1
err = trimspace(<<EOS
job "stack config": ${abspath("main.variant")}:21,47-54: Invalid function argument; Invalid value for "path" parameter: no file exists at config/ue3-globals.yaml; this function works only with files that are distributed as part of the configuration source code, so if this file will be created by a resource in this configuration you must instead obtain this result from an attribute of that resource.
EOS
)
namespace = "UNDEFINED"
region = "UNDEFINED"
environment = "UNDEFINED"
stage = "UNDEFINED"
override_with_empty = "UNDEFINED"
override_with_ints = "UNDEFINED"
}

run "stack config" {
config-dir = "config"
stack = case.stack
}

assert "error" {
condition = run.err == case.err
}

assert "namespace" {
condition = (run.res.set && try(jsondecode(run.res.stdout).vars.namespace, "UNDEFINED") == case.namespace) || !run.res.set
}

assert "region" {
condition = (run.res.set && try(jsondecode(run.res.stdout).vars.region, "UNDEFINED") == case.region) || !run.res.set
}

assert "environment" {
condition = (run.res.set && try(jsondecode(run.res.stdout).vars.environment, "UNDEFINED") == case.environment) || !run.res.set
}

assert "stage" {
condition = (run.res.set && try(jsondecode(run.res.stdout).vars.stage, "UNDEFINED") == case.stage) || !run.res.set
}

assert "override_with_empty" {
condition = (run.res.set && try(jsondecode(run.res.stdout).override_with_empty, "UNDEFINED") == case.override_with_empty) || !run.res.set
}

assert "override_with_ints" {
condition = (run.res.set && try(jsondecode(run.res.stdout).override_with_ints, "UNDEFINED") == case.override_with_ints) || !run.res.set
}

assert "exitstatus" {
condition = (run.res.set && run.res.exitstatus == case.exitstatus) || !run.res.set
}
}

test "userfunc stack config" {
case "ue2-prod" {
stack = "ue2-prod"
exitstatus = 0
err = ""
namespace = "eg"
region = "us-east-2"
environment = "ue2"
stage = "prod"
override_with_empty = []
override_with_ints = [2]
}

// missing stack config
case "ue1-prod" {
stack = "ue1-prod"
exitstatus = 1
err = trimspace(<<EOS
job "userfunc stack config": ${abspath("userfunc.variant")}:25,13-20: Error in function call; Call to function "import" failed: ${abspath("userfunc.variant")}:4,39-46: Invalid function argument; Invalid value for "path" parameter: no file exists at config/ue1-prod.yaml; this function works only with files that are distributed as part of the configuration source code, so if this file will be created by a resource in this configuration you must instead obtain this result from an attribute of that resource..
EOS
)
namespace = "UNDEFINED"
region = "UNDEFINED"
environment = "UNDEFINED"
stage = "UNDEFINED"
override_with_empty = "UNDEFINED"
override_with_ints = "UNDEFINED"
}

// missing stack config import
case "ue3-prod" {
stack = "ue3-prod"
exitstatus = 1
err = trimspace(<<EOS
job "userfunc stack config": ${abspath("userfunc.variant")}:25,13-20: Error in function call; Call to function "import" failed: ${abspath("userfunc.variant")}:6,9-16: Error in function call; Call to function "import" failed: ${abspath("userfunc.variant")}:4,39-46: Invalid function argument; Invalid value for "path" parameter: no file exists at config/ue3-globals.yaml; this function works only with files that are distributed as part of the configuration source code, so if this file will be created by a resource in this configuration you must instead obtain this result from an attribute of that resource...
EOS
)
namespace = "UNDEFINED"
region = "UNDEFINED"
environment = "UNDEFINED"
stage = "UNDEFINED"
override_with_empty = "UNDEFINED"
override_with_ints = "UNDEFINED"
}

run "userfunc stack config" {
config-dir = "config"
stack = case.stack
}

assert "error" {
condition = run.err == case.err
}

assert "namespace" {
condition = (run.res.set && try(jsondecode(run.res.stdout).vars.namespace, "UNDEFINED") == case.namespace) || !run.res.set
}

assert "region" {
condition = (run.res.set && try(jsondecode(run.res.stdout).vars.region, "UNDEFINED") == case.region) || !run.res.set
}

assert "environment" {
condition = (run.res.set && try(jsondecode(run.res.stdout).vars.environment, "UNDEFINED") == case.environment) || !run.res.set
}

assert "stage" {
condition = (run.res.set && try(jsondecode(run.res.stdout).vars.stage, "UNDEFINED") == case.stage) || !run.res.set
}

assert "override_with_empty" {
condition = (run.res.set && try(jsondecode(run.res.stdout).override_with_empty, "UNDEFINED") == case.override_with_empty) || !run.res.set
}

assert "override_with_ints" {
condition = (run.res.set && try(jsondecode(run.res.stdout).override_with_ints, "UNDEFINED") == case.override_with_ints) || !run.res.set
}

assert "exitstatus" {
condition = (run.res.set && run.res.exitstatus == case.exitstatus) || !run.res.set
}
}
40 changes: 40 additions & 0 deletions examples/advanced/dynamic-config-inheritance/userfunc.variant
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
function "import" {
params = [config-dir, path]
result = flatten(concat([
for k, imports in yamldecode(file(format("%s/%s.yaml", config-dir, path))): [
for imported in imports: [
import(config-dir, imported)
]
] if k == "import"
], [
format("%s/%s.yaml", config-dir, path)
]))
}

job "userfunc stack config" {
concurrency = 1
description = "Generate stack config in YAML format"

option "stack" {
type = string
description = "Stack"
short = "s"
}

variable "files" {
value = import(opt.config-dir, opt.stack)
}

config "all" {
source file {
paths = var.files
}
}

exec {
command = "echo"
args = [
jsonencode(conf.all)
]
}
}
5 changes: 5 additions & 0 deletions examples/advanced/userfunc-local-scope/config/globals.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
vars:
namespace: eg

override_with_empty: [1]
override_with_ints: [1]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import:
- globals

vars:
region: us-east-2
environment: ue2

override_with_empty: []
override_with_ints: [2]
5 changes: 5 additions & 0 deletions examples/advanced/userfunc-local-scope/config/ue2-prod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import:
- ue2-globals

vars:
stage: prod
5 changes: 5 additions & 0 deletions examples/advanced/userfunc-local-scope/config/ue3-prod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import:
- ue3-globals

vars:
stage: prod
5 changes: 5 additions & 0 deletions examples/advanced/userfunc-local-scope/main.variant
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import = "../dynamic-config-inheritance"

job "nested" {
import = "../dynamic-config-inheritance"
}
Loading