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

Add metadata.terraform_workspace_pattern #138

Merged
merged 6 commits into from Apr 18, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -40,3 +40,7 @@ components:
val2: "5"
val3: 7
val4: null
metadata:
# Override Terraform workspace
# Note that by default, Terraform workspace is generated from the context, e.g. `<environment>-<stage>`
terraform_workspace_pattern: "{tenant}-{environment}-{stage}-{component}"
37 changes: 37 additions & 0 deletions internal/exec/stack_utils.go
@@ -0,0 +1,37 @@
package exec

import (
"fmt"
c "github.com/cloudposse/atmos/pkg/config"
"strings"
)

// BuildTerraformWorkspace builds Terraform workspace
func BuildTerraformWorkspace(
stack string,
stackNamePattern string,
componentMetadata map[interface{}]interface{},
context c.Context,
) (string, error) {

contextPrefix, err := c.GetContextPrefix(stack, context, stackNamePattern)
if err != nil {
return "", err
}

var workspace string

if terraformWorkspacePattern, terraformWorkspacePatternExist := componentMetadata["terraform_workspace_pattern"].(string); terraformWorkspacePatternExist {
// Terraform workspace can be overridden per component in YAML config `metadata.terraform_workspace_pattern`
workspace = c.ReplaceContextTokens(context, terraformWorkspacePattern)
} else if terraformWorkspace, terraformWorkspaceExist := componentMetadata["terraform_workspace"].(string); terraformWorkspaceExist {
// Terraform workspace can be overridden per component in YAML config `metadata.terraform_workspace`
workspace = terraformWorkspace
} else if context.BaseComponent == "" {
workspace = contextPrefix
} else {
workspace = fmt.Sprintf("%s-%s", contextPrefix, context.Component)
}

return strings.Replace(workspace, "/", "-", -1), nil
}
21 changes: 11 additions & 10 deletions internal/exec/utils.go
Expand Up @@ -417,23 +417,23 @@ func ProcessStacks(configAndStacksInfo c.ConfigAndStacksInfo, checkStack bool) (

// Process context
configAndStacksInfo.Context = c.GetContextFromVars(configAndStacksInfo.ComponentVarsSection)
configAndStacksInfo.Context.Component = configAndStacksInfo.ComponentFromArg
configAndStacksInfo.Context.BaseComponent = configAndStacksInfo.BaseComponentPath
configAndStacksInfo.ContextPrefix, err = c.GetContextPrefix(configAndStacksInfo.Stack, configAndStacksInfo.Context, c.Config.Stacks.NamePattern)
if err != nil {
return configAndStacksInfo, err
}

// workspace
var workspace string
// Terraform workspace can be overridden per component in YAML config `metadata.terraform_workspace`
if componentTerraformWorkspace, componentTerraformWorkspaceExist := configAndStacksInfo.ComponentMetadataSection["terraform_workspace"].(string); componentTerraformWorkspaceExist {
workspace = componentTerraformWorkspace
} else if len(configAndStacksInfo.BaseComponent) == 0 {
workspace = configAndStacksInfo.ContextPrefix
} else {
workspace = fmt.Sprintf("%s-%s", configAndStacksInfo.ContextPrefix, configAndStacksInfo.ComponentFromArg)
workspace, err := BuildTerraformWorkspace(
configAndStacksInfo.Stack,
c.Config.Stacks.NamePattern,
configAndStacksInfo.ComponentMetadataSection,
configAndStacksInfo.Context,
)
if err != nil {
return configAndStacksInfo, err
}

workspace = strings.Replace(workspace, "/", "-", -1)
configAndStacksInfo.TerraformWorkspace = workspace
configAndStacksInfo.ComponentSection["workspace"] = workspace

Expand Down Expand Up @@ -637,6 +637,7 @@ func processArgsAndFlags(inputArgsAndFlags []string) (c.ArgsAndFlagsInfo, error)
return info, nil
}

// generateComponentBackendConfig generates backend config for components
func generateComponentBackendConfig(backendType string, backendConfig map[interface{}]interface{}) map[string]interface{} {
return map[string]interface{}{
"terraform": map[string]interface{}{
Expand Down
13 changes: 7 additions & 6 deletions pkg/config/schema.go
Expand Up @@ -56,12 +56,13 @@ type ProcessedConfiguration struct {
}

type Context struct {
Namespace string
Tenant string
Environment string
Stage string
Region string
Component string
Namespace string
Tenant string
Environment string
Stage string
Region string
Component string
BaseComponent string
}

type ArgsAndFlagsInfo struct {
Expand Down
4 changes: 3 additions & 1 deletion pkg/config/utils.go
Expand Up @@ -434,7 +434,9 @@ func ReplaceContextTokens(context Context, pattern string) string {
strings.Replace(
strings.Replace(
strings.Replace(
strings.Replace(pattern,
strings.Replace(
strings.Replace(pattern,
"{base-component}", context.BaseComponent, 1),
aknysh marked this conversation as resolved.
Show resolved Hide resolved
"{component}", context.Component, 1),
"{namespace}", context.Namespace, 1),
"{environment}", context.Environment, 1),
Expand Down
39 changes: 24 additions & 15 deletions pkg/spacelift/spacelift_stack_processor.go
Expand Up @@ -2,6 +2,7 @@ package spacelift

import (
"fmt"
e "github.com/cloudposse/atmos/internal/exec"
c "github.com/cloudposse/atmos/pkg/config"
s "github.com/cloudposse/atmos/pkg/stack"
u "github.com/cloudposse/atmos/pkg/utils"
Expand Down Expand Up @@ -366,7 +367,21 @@ func TransformStackConfigToSpaceliftStacks(
componentInheritance = i.([]string)
}

baseComponentName := ""
if baseComponent, baseComponentExist := componentMap["component"]; baseComponentExist {
baseComponentName = baseComponent.(string)
}

if componentMetadata, componentMetadataExists := componentMap["metadata"].(map[interface{}]interface{}); componentMetadataExists {
if componentMetadataComponent, componentMetadataComponentExists := componentMetadata["component"].(string); componentMetadataComponentExists {
aknysh marked this conversation as resolved.
Show resolved Hide resolved
baseComponentName = componentMetadataComponent
}
}

context := c.GetContextFromVars(componentVars)
context.Component = component
context.BaseComponent = baseComponentName

contextPrefix, err := c.GetContextPrefix(stackName, context, stackNamePattern)
if err != nil {
return nil, err
Expand All @@ -381,11 +396,6 @@ func TransformStackConfigToSpaceliftStacks(
spaceliftConfig["deps"] = componentDeps
spaceliftConfig["stacks"] = componentStacks
spaceliftConfig["inheritance"] = componentInheritance

baseComponentName := ""
if baseComponent, baseComponentExist := componentMap["component"]; baseComponentExist {
baseComponentName = baseComponent.(string)
}
spaceliftConfig["base_component"] = baseComponentName

// backend
Expand All @@ -409,16 +419,16 @@ func TransformStackConfigToSpaceliftStacks(
spaceliftConfig["metadata"] = componentMetadata

// workspace
var workspace string
// Terraform workspace can be overridden per component in YAML config `metadata.terraform_workspace`
if componentTerraformWorkspace, componentTerraformWorkspaceExist := componentMetadata["terraform_workspace"].(string); componentTerraformWorkspaceExist {
workspace = componentTerraformWorkspace
} else if backendTypeName == "s3" && baseComponentName == "" {
workspace = contextPrefix
} else {
workspace = fmt.Sprintf("%s-%s", contextPrefix, component)
workspace, err := e.BuildTerraformWorkspace(
stackName,
stackNamePattern,
componentMetadata,
context,
)
if err != nil {
return nil, err
}
spaceliftConfig["workspace"] = strings.Replace(workspace, "/", "-", -1)
spaceliftConfig["workspace"] = workspace

// labels
labels := []string{}
Expand Down Expand Up @@ -460,7 +470,6 @@ func TransformStackConfigToSpaceliftStacks(
spaceliftConfig["labels"] = u.UniqueStrings(labels)

// Spacelift stack name
context.Component = component
spaceliftStackName, spaceliftStackNamePattern := buildSpaceliftStackName(spaceliftSettings, context, contextPrefix)

// Add Spacelift stack config to the final map
Expand Down