Skip to content

Commit

Permalink
Fix processing of Spacelift stack dependencies using `settings.depend…
Browse files Browse the repository at this point in the history
…s_on` config. Implement double-dash `--` handling for `terraform` and `helmfile` commands (#472)

* Update Spacelift `depends_on`

* Update `settings.depends_on` for Spacelift

* Update `settings.depends_on` for Spacelift

* IMplement double-dash `--` handling for `terraform` and `helmfile` commands

* IMplement double-dash `--` handling for `terraform` and `helmfile` commands
  • Loading branch information
aknysh authored Nov 4, 2023
1 parent fc5357b commit 6184f7f
Show file tree
Hide file tree
Showing 24 changed files with 112 additions and 36 deletions.
15 changes: 13 additions & 2 deletions cmd/helmfile.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package cmd

import (
"github.com/samber/lo"
"github.com/spf13/cobra"

e "github.com/cloudposse/atmos/internal/exec"
u "github.com/cloudposse/atmos/pkg/utils"
"github.com/spf13/cobra"
)

// helmfileCmd represents the base command for all helmfile sub-commands
Expand All @@ -13,7 +15,16 @@ var helmfileCmd = &cobra.Command{
Long: `This command runs helmfile commands`,
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: true},
Run: func(cmd *cobra.Command, args []string) {
err := e.ExecuteHelmfileCmd(cmd, args)
var argsAfterDoubleDash []string
var finalArgs = args

doubleDashIndex := lo.IndexOf(args, "--")
if doubleDashIndex > 0 {
finalArgs = lo.Slice(args, 0, doubleDashIndex)
argsAfterDoubleDash = lo.Slice(args, doubleDashIndex+1, len(args))
}

err := e.ExecuteHelmfileCmd(cmd, finalArgs, argsAfterDoubleDash)
if err != nil {
u.LogErrorAndExit(err)
}
Expand Down
15 changes: 13 additions & 2 deletions cmd/terraform.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package cmd

import (
"github.com/samber/lo"
"github.com/spf13/cobra"

e "github.com/cloudposse/atmos/internal/exec"
u "github.com/cloudposse/atmos/pkg/utils"
"github.com/spf13/cobra"
)

// terraformCmd represents the base command for all terraform sub-commands
Expand All @@ -13,7 +15,16 @@ var terraformCmd = &cobra.Command{
Long: `This command runs terraform commands`,
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: true},
Run: func(cmd *cobra.Command, args []string) {
err := e.ExecuteTerraformCmd(cmd, args)
var argsAfterDoubleDash []string
var finalArgs = args

doubleDashIndex := lo.IndexOf(args, "--")
if doubleDashIndex > 0 {
finalArgs = lo.Slice(args, 0, doubleDashIndex)
argsAfterDoubleDash = lo.Slice(args, doubleDashIndex+1, len(args))
}

err := e.ExecuteTerraformCmd(cmd, finalArgs, argsAfterDoubleDash)
if err != nil {
u.LogErrorAndExit(err)
}
Expand Down
6 changes: 3 additions & 3 deletions examples/complete/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Geodesic: https://github.com/cloudposse/geodesic/
ARG GEODESIC_VERSION=2.7.0
ARG GEODESIC_VERSION=2.7.2
ARG GEODESIC_OS=debian

# atmos: https://github.com/cloudposse/atmos
ARG ATMOS_VERSION=1.48.0
ARG ATMOS_VERSION=1.50.0

# Terraform: https://github.com/hashicorp/terraform/releases
ARG TF_VERSION=1.6.2
ARG TF_VERSION=1.6.3

FROM cloudposse/geodesic:${GEODESIC_VERSION}-${GEODESIC_OS}

Expand Down
2 changes: 1 addition & 1 deletion internal/exec/atlantis_generate_repo_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

// ExecuteAtlantisGenerateRepoConfigCmd executes 'atlantis generate repo-config' command
func ExecuteAtlantisGenerateRepoConfigCmd(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("", cmd, args)
info, err := processCommandLineArgs("", cmd, args, nil)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/describe_affected.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

// ExecuteDescribeAffectedCmd executes `describe affected` command
func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("", cmd, args)
info, err := processCommandLineArgs("", cmd, args, nil)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/describe_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func ExecuteDescribeConfigCmd(cmd *cobra.Command, args []string) error {
return err
}

info, err := processCommandLineArgs("", cmd, args)
info, err := processCommandLineArgs("", cmd, args, nil)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/describe_dependents.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

// ExecuteDescribeDependentsCmd executes `describe dependents` command
func ExecuteDescribeDependentsCmd(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("", cmd, args)
info, err := processCommandLineArgs("", cmd, args, nil)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/describe_stacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

// ExecuteDescribeStacksCmd executes `describe stacks` command
func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("", cmd, args)
info, err := processCommandLineArgs("", cmd, args, nil)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/exec/helmfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
)

// ExecuteHelmfileCmd parses the provided arguments and flags and executes helmfile commands
func ExecuteHelmfileCmd(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("helmfile", cmd, args)
func ExecuteHelmfileCmd(cmd *cobra.Command, args []string, additionalArgsAndFlags []string) error {
info, err := processCommandLineArgs("helmfile", cmd, args, additionalArgsAndFlags)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/helmfile_generate_varfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func ExecuteHelmfileGenerateVarfileCmd(cmd *cobra.Command, args []string) error

component := args[0]

info, err := processCommandLineArgs("helmfile", cmd, args)
info, err := processCommandLineArgs("helmfile", cmd, args, nil)
if err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions internal/exec/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ func processHelp(componentType string, command string) error {
u.PrintMessage(" - 'atmos terraform generate varfiles' command generates varfiles for all 'atmos' components in all stacks")
u.PrintMessage(" - 'atmos terraform shell' command configures an environment for an 'atmos' component in a stack and starts a new shell " +
"allowing executing all native terraform commands inside the shell without using atmos-specific arguments and flags")
u.PrintMessage(" - double-dash '--' can be used to signify the end of the options for Atmos and the start of the additional " +
"native arguments and flags for the 'terraform' commands. " +
"For example: atmos terraform plan <component> -s <stack> -- -refresh=false -lock=false")
}

if componentType == "helmfile" {
Expand All @@ -52,6 +55,8 @@ func processHelp(componentType string, command string) error {
u.PrintMessage(" - before executing the 'helmfile' commands, 'atmos' runs 'aws eks update-kubeconfig' to read kubeconfig from " +
"the EKS cluster and use it to authenticate with the cluster. This can be disabled in 'atmos.yaml' CLI config " +
"by setting 'components.helmfile.use_eks' to 'false'")
u.PrintMessage(" - double-dash '--' can be used to signify the end of the options for Atmos and the start of the additional " +
"native arguments and flags for the 'helmfile' commands")
}

err := ExecuteShellCommand(cliConfig, componentType, []string{"--help"}, "", nil, false, "")
Expand Down
33 changes: 30 additions & 3 deletions internal/exec/stack_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ func ProcessComponentMetadata(
return componentMetadata, baseComponentName, componentIsAbstract
}

// BuildDependentStackNameFromDependsOn builds the dependent stack name from "depends_on" attribute
func BuildDependentStackNameFromDependsOn(
// BuildDependentStackNameFromDependsOnLegacy builds the dependent stack name from "settings.spacelift.depends_on" config
func BuildDependentStackNameFromDependsOnLegacy(
dependsOn string,
allStackNames []string,
currentStackName string,
Expand All @@ -104,14 +104,41 @@ func BuildDependentStackNameFromDependsOn(
"but '%[3]s' is not a stack and not a component in the '%[2]s' stack",
currentComponentName,
currentStackName,
dependsOn)
dependsOn,
)

return "", errorMessage
}

return dependentStackName, nil
}

// BuildDependentStackNameFromDependsOn builds the dependent stack name from "settings.depends_on" config
func BuildDependentStackNameFromDependsOn(
currentComponentName string,
currentStackName string,
dependsOnComponentName string,
dependsOnStackName string,
allStackNames []string,
) (string, error) {

dep := strings.Replace(fmt.Sprintf("%s-%s", dependsOnStackName, dependsOnComponentName), "/", "-", -1)

if u.SliceContainsString(allStackNames, dep) {
return dep, nil
}

errorMessage := fmt.Errorf("the component '%[1]s' in the stack '%[2]s' specifies 'settings.depends_on' dependency "+
"on the component '%[3]s' in the stack '%[4]s', but '%[3]s' is not defined in the '%[4]s' stack, or the component and stack names are not correct",
currentComponentName,
currentStackName,
dependsOnComponentName,
dependsOnStackName,
)

return "", errorMessage
}

// BuildComponentPath builds component path (path to the component's physical location on disk)
func BuildComponentPath(
cliConfig schema.CliConfiguration,
Expand Down
4 changes: 2 additions & 2 deletions internal/exec/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const (
)

// ExecuteTerraformCmd parses the provided arguments and flags and executes terraform commands
func ExecuteTerraformCmd(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("terraform", cmd, args)
func ExecuteTerraformCmd(cmd *cobra.Command, args []string, additionalArgsAndFlags []string) error {
info, err := processCommandLineArgs("terraform", cmd, args, additionalArgsAndFlags)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/terraform_generate_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func ExecuteTerraformGenerateBackendCmd(cmd *cobra.Command, args []string) error

component := args[0]

info, err := processCommandLineArgs("terraform", cmd, args)
info, err := processCommandLineArgs("terraform", cmd, args, nil)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/terraform_generate_backends.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

// ExecuteTerraformGenerateBackendsCmd executes `terraform generate backends` command
func ExecuteTerraformGenerateBackendsCmd(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("terraform", cmd, args)
info, err := processCommandLineArgs("terraform", cmd, args, nil)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/terraform_generate_varfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func ExecuteTerraformGenerateVarfileCmd(cmd *cobra.Command, args []string) error

component := args[0]

info, err := processCommandLineArgs("terraform", cmd, args)
info, err := processCommandLineArgs("terraform", cmd, args, nil)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/terraform_generate_varfiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

// ExecuteTerraformGenerateVarfilesCmd executes `terraform generate varfiles` command
func ExecuteTerraformGenerateVarfilesCmd(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("terraform", cmd, args)
info, err := processCommandLineArgs("terraform", cmd, args, nil)
if err != nil {
return err
}
Expand Down
14 changes: 12 additions & 2 deletions internal/exec/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,12 @@ func FindComponentConfig(
}

// processCommandLineArgs processes command-line args
func processCommandLineArgs(componentType string, cmd *cobra.Command, args []string) (schema.ConfigAndStacksInfo, error) {
func processCommandLineArgs(
componentType string,
cmd *cobra.Command,
args []string,
additionalArgsAndFlags []string,
) (schema.ConfigAndStacksInfo, error) {
var configAndStacksInfo schema.ConfigAndStacksInfo

cmd.DisableFlagParsing = false
Expand All @@ -165,7 +170,12 @@ func processCommandLineArgs(componentType string, cmd *cobra.Command, args []str
return configAndStacksInfo, err
}

configAndStacksInfo.AdditionalArgsAndFlags = argsAndFlagsInfo.AdditionalArgsAndFlags
finalAdditionalArgsAndFlags := argsAndFlagsInfo.AdditionalArgsAndFlags
if len(additionalArgsAndFlags) > 0 {
finalAdditionalArgsAndFlags = append(finalAdditionalArgsAndFlags, additionalArgsAndFlags...)
}

configAndStacksInfo.AdditionalArgsAndFlags = finalAdditionalArgsAndFlags
configAndStacksInfo.SubCommand = argsAndFlagsInfo.SubCommand
configAndStacksInfo.SubCommand2 = argsAndFlagsInfo.SubCommand2
configAndStacksInfo.ComponentType = componentType
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/validate_component.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

// ExecuteValidateComponentCmd executes `validate component` command
func ExecuteValidateComponentCmd(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("", cmd, args)
info, err := processCommandLineArgs("", cmd, args, nil)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/vendor_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (

// ExecuteVendorPullCommand executes `atmos vendor` commands
func ExecuteVendorPullCommand(cmd *cobra.Command, args []string) error {
info, err := processCommandLineArgs("terraform", cmd, args)
info, err := processCommandLineArgs("terraform", cmd, args, nil)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/worflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func ExecuteWorkflowCmd(cmd *cobra.Command, args []string) error {
return errors.New("invalid arguments. The command requires one argument `workflow name`")
}

info, err := processCommandLineArgs("terraform", cmd, args)
info, err := processCommandLineArgs("terraform", cmd, args, nil)
if err != nil {
return err
}
Expand Down
16 changes: 9 additions & 7 deletions pkg/spacelift/spacelift_stack_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ func TransformStackConfigToSpaceliftStacks(

var terraformComponentNamesInCurrentStack []string

for v := range terraformComponentsMap {
terraformComponentNamesInCurrentStack = append(terraformComponentNamesInCurrentStack, strings.Replace(v, "/", "-", -1))
for v2 := range terraformComponentsMap {
terraformComponentNamesInCurrentStack = append(terraformComponentNamesInCurrentStack, strings.Replace(v2, "/", "-", -1))
}

// Legacy/deprecated `settings.spacelift.depends_on`
Expand All @@ -276,12 +276,13 @@ func TransformStackConfigToSpaceliftStacks(
var spaceliftStackNameDependsOnLabels1 []string

for _, dep := range spaceliftDependsOn {
spaceliftStackNameDependsOn, err := e.BuildDependentStackNameFromDependsOn(
spaceliftStackNameDependsOn, err := e.BuildDependentStackNameFromDependsOnLegacy(
dep.(string),
allStackNames,
contextPrefix,
terraformComponentNamesInCurrentStack,
component)
component,
)
if err != nil {
u.LogError(err)
return nil, err
Expand Down Expand Up @@ -336,11 +337,12 @@ func TransformStackConfigToSpaceliftStacks(
}

spaceliftStackNameDependsOn, err := e.BuildDependentStackNameFromDependsOn(
component,
contextPrefix,
stackComponentSettingsDependsOnContext.Component,
allStackNames,
contextPrefixDependsOn,
terraformComponentNamesInCurrentStack,
component)
allStackNames,
)
if err != nil {
u.LogError(err)
return nil, err
Expand Down
3 changes: 3 additions & 0 deletions website/docs/cli/commands/helmfile/usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ In addition, the `component` argument and `stack` flag are required to generate
- before executing the `helmfile` commands, Atmos runs `aws eks update-kubeconfig` to read kubeconfig from the EKS cluster and use it to
authenticate with the cluster. This can be disabled in `atmos.yaml` CLI config by setting `components.helmfile.use_eks` to `false`

- double-dash `--` can be used to signify the end of the options for Atmos and the start of the additional native arguments and flags for
the `helmfile` commands.

<br/>

:::tip
Expand Down
7 changes: 7 additions & 0 deletions website/docs/cli/commands/terraform/usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ In addition, the `component` argument and `stack` flag are required to generate
- `atmos terraform shell` command configures an environment for an Atmos component in a stack and starts a new shell allowing executing all native
terraform commands inside the shell

- double-dash `--` can be used to signify the end of the options for Atmos and the start of the additional native arguments and flags for
the `terraform` commands. For example:
- `atmos terraform plan <component> -s <stack> -- -refresh=false`
- `atmos terraform apply <component> -s <stack> -- -lock=false`

<br />

:::tip
Expand Down Expand Up @@ -102,6 +107,8 @@ atmos terraform workspace test/test-component-override-3 -s tenant1-ue2-dev
atmos terraform workspace test/test-component-override-3 -s tenant1-ue2-dev --redirect-stderr /dev/null
atmos terraform workspace test/test-component-override-3 -s tenant1-ue2-dev --redirect-stderr /dev/stdout
atmos terraform workspace test/test-component-override-3 -s tenant1-ue2-dev --redirect-stderr ./errors.txt

atmos terraform plan test/test-component -s tenant1-ue2-dev -- -refresh=false -lock=false
```

## Arguments
Expand Down

0 comments on commit 6184f7f

Please sign in to comment.