-
-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Update stack and spacelift packages * Update stack and spacelift packages * Update stack and spacelift packages * Update stack and spacelift packages * Update stack and spacelift packages * Update stack and spacelift packages * Update stack and spacelift packages * Update stack and spacelift packages
- Loading branch information
Showing
15 changed files
with
526 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# CLI config is loaded from the following locations (from lowest to highest priority): | ||
# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows) | ||
# home dir (~/.atmos) | ||
# current directory | ||
# ENV vars | ||
# Command-line arguments | ||
# | ||
# It supports POSIX-style Globs for file names/paths (double-star `**` is supported) | ||
# https://en.wikipedia.org/wiki/Glob_(programming) | ||
|
||
components: | ||
terraform: | ||
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument | ||
# Supports both absolute and relative paths | ||
base_path: "../../examples/complete/components/terraform" | ||
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var | ||
apply_auto_approve: false | ||
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument | ||
deploy_run_init: true | ||
helmfile: | ||
# Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, or `--helmfile-dir` command-line argument | ||
# Supports both absolute and relative paths | ||
base_path: "../../examples/complete/components/helmfile" | ||
# Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var | ||
kubeconfig_path: "/dev/shm" | ||
# Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var | ||
helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" | ||
# Can also be set using `ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var | ||
cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" | ||
|
||
stacks: | ||
# Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments | ||
# Supports both absolute and relative paths | ||
base_path: "../../examples/complete/stacks" | ||
# Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string) | ||
included_paths: | ||
- "**/*" | ||
# Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string) | ||
excluded_paths: | ||
- "globals/**/*" | ||
- "catalog/**/*" | ||
- "**/*globals*" | ||
# Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var | ||
name_pattern: "{tenant}-{environment}-{stage}" | ||
|
||
logs: | ||
verbose: false | ||
colors: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
package component | ||
|
||
import ( | ||
"fmt" | ||
c "github.com/cloudposse/atmos/internal/config" | ||
s "github.com/cloudposse/atmos/pkg/stack" | ||
"github.com/pkg/errors" | ||
"strings" | ||
) | ||
|
||
// ProcessComponentInStack accepts a component and a stack name and returns the component configuration in the stack | ||
func ProcessComponentInStack(component string, stack string) (map[string]interface{}, error) { | ||
var configAndStacksInfo c.ConfigAndStacksInfo | ||
configAndStacksInfo.Stack = stack | ||
|
||
err := c.InitConfig() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = c.ProcessConfig(configAndStacksInfo) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
_, stacksMap, err := s.ProcessYAMLConfigFiles( | ||
c.ProcessedConfig.StacksBaseAbsolutePath, | ||
c.ProcessedConfig.StackConfigFilesAbsolutePaths, | ||
true, | ||
true) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var componentSection map[string]interface{} | ||
var componentVarsSection map[interface{}]interface{} | ||
|
||
// Check and process stacks | ||
if c.ProcessedConfig.StackType == "Directory" { | ||
componentSection, componentVarsSection, _, err = findComponentConfig(stack, stacksMap, "terraform", component) | ||
if err != nil { | ||
componentSection, componentVarsSection, _, err = findComponentConfig(stack, stacksMap, "helmfile", component) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
} else { | ||
if len(c.Config.Stacks.NamePattern) < 1 { | ||
return nil, errors.New("stack name pattern must be provided in 'stacks.name_pattern' config or 'ATMOS_STACKS_NAME_PATTERN' ENV variable") | ||
} | ||
|
||
stackParts := strings.Split(stack, "-") | ||
stackNamePatternParts := strings.Split(c.Config.Stacks.NamePattern, "-") | ||
|
||
var tenant string | ||
var environment string | ||
var stage string | ||
var tenantFound bool | ||
var environmentFound bool | ||
var stageFound bool | ||
|
||
for i, part := range stackNamePatternParts { | ||
if part == "{tenant}" { | ||
tenant = stackParts[i] | ||
} else if part == "{environment}" { | ||
environment = stackParts[i] | ||
} else if part == "{stage}" { | ||
stage = stackParts[i] | ||
} | ||
} | ||
|
||
for stackName := range stacksMap { | ||
componentSection, componentVarsSection, _, err = findComponentConfig(stackName, stacksMap, "terraform", component) | ||
if err != nil { | ||
componentSection, componentVarsSection, _, err = findComponentConfig(stackName, stacksMap, "helmfile", component) | ||
if err != nil { | ||
continue | ||
} | ||
} | ||
|
||
tenantFound = true | ||
environmentFound = true | ||
stageFound = true | ||
|
||
// Search for tenant in stack | ||
if len(tenant) > 0 { | ||
if tenantInStack, ok := componentVarsSection["tenant"].(string); !ok || tenantInStack != tenant { | ||
tenantFound = false | ||
} | ||
} | ||
|
||
// Search for environment in stack | ||
if len(environment) > 0 { | ||
if environmentInStack, ok := componentVarsSection["environment"].(string); !ok || environmentInStack != environment { | ||
environmentFound = false | ||
} | ||
} | ||
|
||
// Search for stage in stack | ||
if len(stage) > 0 { | ||
if stageInStack, ok := componentVarsSection["stage"].(string); !ok || stageInStack != stage { | ||
stageFound = false | ||
} | ||
} | ||
|
||
if tenantFound == true && environmentFound == true && stageFound == true { | ||
stack = stackName | ||
break | ||
} | ||
} | ||
|
||
if tenantFound == false || environmentFound == false || stageFound == false { | ||
return nil, errors.New(fmt.Sprintf("\nCould not find config for the component '%s' in the stack '%s'.\n"+ | ||
"Check that all attributes in the stack name pattern '%s' are defined in stack config files.\n"+ | ||
"Are the component and stack names correct? Did you forget an import?", | ||
component, | ||
stack, | ||
c.Config.Stacks.NamePattern, | ||
)) | ||
} | ||
} | ||
|
||
baseComponentName := "" | ||
if baseComponent, baseComponentExist := componentSection["component"]; baseComponentExist { | ||
baseComponentName = baseComponent.(string) | ||
} | ||
|
||
// workspace | ||
var workspace string | ||
if len(baseComponentName) == 0 { | ||
workspace = stack | ||
} else { | ||
workspace = fmt.Sprintf("%s-%s", stack, component) | ||
} | ||
componentSection["workspace"] = strings.Replace(workspace, "/", "-", -1) | ||
|
||
return componentSection, nil | ||
} | ||
|
||
// ProcessComponentFromContext accepts context (tenant, environment, stage) and returns the component configuration in the stack | ||
func ProcessComponentFromContext(component string, tenant string, environment string, stage string) (map[string]interface{}, error) { | ||
var stack string | ||
|
||
err := c.InitConfig() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if len(c.Config.Stacks.NamePattern) < 1 { | ||
return nil, errors.New("stack name pattern must be provided in 'stacks.name_pattern' config or 'ATMOS_STACKS_NAME_PATTERN' ENV variable") | ||
} | ||
|
||
stackNamePatternParts := strings.Split(c.Config.Stacks.NamePattern, "-") | ||
|
||
for _, part := range stackNamePatternParts { | ||
if part == "{tenant}" { | ||
if len(tenant) == 0 { | ||
return nil, errors.New(fmt.Sprintf("stack name pattern '%s' includes '{tenant}', but tenant is not provided", c.Config.Stacks.NamePattern)) | ||
} | ||
if len(stack) == 0 { | ||
stack = tenant | ||
} else { | ||
stack = fmt.Sprintf("%s-%s", stack, tenant) | ||
} | ||
} else if part == "{environment}" { | ||
if len(environment) == 0 { | ||
return nil, errors.New(fmt.Sprintf("stack name pattern '%s' includes '{environment}', but environment is not provided", c.Config.Stacks.NamePattern)) | ||
} | ||
if len(stack) == 0 { | ||
stack = environment | ||
} else { | ||
stack = fmt.Sprintf("%s-%s", stack, environment) | ||
} | ||
} else if part == "{stage}" { | ||
if len(stage) == 0 { | ||
return nil, errors.New(fmt.Sprintf("stack name pattern '%s' includes '{stage}', but stage is not provided", c.Config.Stacks.NamePattern)) | ||
} | ||
if len(stack) == 0 { | ||
stack = stage | ||
} else { | ||
stack = fmt.Sprintf("%s-%s", stack, stage) | ||
} | ||
} | ||
} | ||
|
||
return ProcessComponentInStack(component, stack) | ||
} | ||
|
||
// findComponentConfig finds component config sections | ||
func findComponentConfig( | ||
stack string, | ||
stacksMap map[string]interface{}, | ||
componentType string, | ||
component string, | ||
) (map[string]interface{}, map[interface{}]interface{}, map[interface{}]interface{}, error) { | ||
|
||
var stackSection map[interface{}]interface{} | ||
var componentsSection map[string]interface{} | ||
var componentTypeSection map[string]interface{} | ||
var componentSection map[string]interface{} | ||
var componentVarsSection map[interface{}]interface{} | ||
var componentBackendSection map[interface{}]interface{} | ||
var ok bool | ||
|
||
if len(stack) == 0 { | ||
return nil, nil, nil, errors.New("Stack must be provided and must not be empty") | ||
} | ||
if len(component) == 0 { | ||
return nil, nil, nil, errors.New("Component must be provided and must not be empty") | ||
} | ||
if len(componentType) == 0 { | ||
return nil, nil, nil, errors.New("Component type must be provided and must not be empty") | ||
} | ||
if stackSection, ok = stacksMap[stack].(map[interface{}]interface{}); !ok { | ||
return nil, nil, nil, errors.New(fmt.Sprintf("Stack '%s' does not exist", stack)) | ||
} | ||
if componentsSection, ok = stackSection["components"].(map[string]interface{}); !ok { | ||
return nil, nil, nil, errors.New(fmt.Sprintf("'components' section is missing in the stack '%s'", stack)) | ||
} | ||
if componentTypeSection, ok = componentsSection[componentType].(map[string]interface{}); !ok { | ||
return nil, nil, nil, errors.New(fmt.Sprintf("'components/%s' section is missing in the stack '%s'", componentType, stack)) | ||
} | ||
if componentSection, ok = componentTypeSection[component].(map[string]interface{}); !ok { | ||
return nil, nil, nil, errors.New(fmt.Sprintf("Invalid or missing configuration for the component '%s' in the stack '%s'", component, stack)) | ||
} | ||
if componentVarsSection, ok = componentSection["vars"].(map[interface{}]interface{}); !ok { | ||
return nil, nil, nil, errors.New(fmt.Sprintf("Missing 'vars' section for the component '%s' in the stack '%s'", component, stack)) | ||
} | ||
if componentBackendSection, ok = componentSection["backend"].(map[interface{}]interface{}); !ok { | ||
componentBackendSection = nil | ||
} | ||
|
||
return componentSection, componentVarsSection, componentBackendSection, nil | ||
} |
Oops, something went wrong.