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 "ignore_atlantis_dependencies" local variable #356

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,40 @@ If you specify `extra_atlantis_dependencies` in the parent Terragrunt module, th
2. Absolute paths will work as they would in a child module, and the path in the output will be relative from the child module to the absolute path
3. Relative paths, like the string `"foo.json"`, will be evaluated as relative to the Child module. This means that if you need something relative to the parent module, you should use something like `"${get_parent_terragrunt_dir()}/foo.json"`

## Ignoring dependencies

Similarly to `extra_atlantis_dependencies`, we can also ignore dependencies by the name of the file, or the name of the dependency block:


```hcl
dependency "ignore_me" {
config_path = find_in_parent_folders("ignore_me")
}

dependency "ignore_me_block" {
config_path = find_in_parent_folders("ignore_me")
}


locals {
ignore_atlantis_dependencies = [
find_in_parent_folders("ignore_me/terragrunt.hcl"),
"ignore_me_block"
]
}
```

In your `atlantis.yaml` file, there dependency shouldn't be there:

```yaml
- autoplan:
enabled: false
when_modified:
- "*.hcl"
- "*.tf*"
dir: example-setup/ignore_dependency
```

## All Flags

One way to customize the behavior of this module is through CLI flag values passed in at runtime. These settings will apply to all modules.
Expand Down Expand Up @@ -157,7 +191,8 @@ Another way to customize the output is to use `locals` values in your terragrunt
| `atlantis_autoplan` | Allows overriding the `--autoplan` flag for a single module | bool |
| `atlantis_skip` | If true on a child module, that module will not appear in the output.<br>If true on a parent module, none of that parent's children will appear in the output. | bool |
| `extra_atlantis_dependencies` | See [Extra dependencies](https://github.com/transcend-io/terragrunt-atlantis-config#extra-dependencies) | list(string) |
| `atlantis_project` | Create Atlantis project for a project hcl file. Only functional with `--project-hcl-files` and `--use-project-markers` | bool |
| `ignore_atlantis_dependencies` | See [Ignoring dependencies](https://github.com/transcend-io/terragrunt-atlantis-config#Ignoring-dependencies) | list(string) |
| `atlantis_project` | Create Atlantis project for a project hcl file. Only functional with `--project-hcl-files` and `--use-project-markers` | bool |

## Separate workspace for parallel plan and apply

Expand Down
23 changes: 21 additions & 2 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"strings"
"sync"
)
Expand Down Expand Up @@ -120,6 +121,14 @@ func sliceUnion(a, b []string) []string {
return a
}

// Removes strings in toRemove from removeFrom.
func sliceDifference(removeFrom, elementsToRemove []string) []string {
return slices.DeleteFunc(removeFrom, func(dep string) bool {
return slices.Contains(elementsToRemove, dep)
})

}

// Parses the terragrunt config at `path` to find all modules it depends on
func getDependencies(path string, terragruntOptions *options.TerragruntOptions) ([]string, error) {
res, err, _ := requestGroup.Do(path, func() (interface{}, error) {
Expand Down Expand Up @@ -175,7 +184,11 @@ func getDependencies(path string, terragruntOptions *options.TerragruntOptions)

// Get deps from `dependencies` and `dependency` blocks
if parsedConfig.Dependencies != nil && !ignoreDependencyBlocks {
for _, parsedPaths := range parsedConfig.Dependencies.Paths {
for depInd, parsedPaths := range parsedConfig.Dependencies.Paths {
depName := parsedConfig.TerragruntDependencies[depInd].Name
if locals.IgnoreAtlantisDependencies != nil && slices.Contains(locals.IgnoreAtlantisDependencies, depName) {
continue
}
dependencies = append(dependencies, filepath.Join(parsedPaths, "terragrunt.hcl"))
}
}
Expand Down Expand Up @@ -246,9 +259,15 @@ func getDependencies(path string, terragruntOptions *options.TerragruntOptions)
}
}

var ignoreRemoved = nonEmptyDeps
// Remove deps from locals
if locals.IgnoreAtlantisDependencies != nil {
ignoreRemoved = sliceDifference(ignoreRemoved, locals.IgnoreAtlantisDependencies)
}

// Recurse to find dependencies of all dependencies
cascadedDeps := []string{}
for _, dep := range nonEmptyDeps {
for _, dep := range ignoreRemoved {
cascadedDeps = append(cascadedDeps, dep)

// The "cascading" feature is protected by a flag
Expand Down
36 changes: 36 additions & 0 deletions cmd/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ func TestExtraDeclaredDependencies(t *testing.T) {
})
}

func TestIgnoreDependencies(t *testing.T) {
runTest(t, filepath.Join("golden", "ignore_dependencies.yaml"), []string{
"--root",
filepath.Join("..", "test_examples", "ignore_dependency"),
})
}

func TestLocalTerraformModuleSource(t *testing.T) {
runTest(t, filepath.Join("golden", "local_terraform_module.yaml"), []string{
"--root",
Expand Down Expand Up @@ -660,3 +667,32 @@ func TestWithDependsOn(t *testing.T) {
"--create-project-name",
})
}

func TestSliceDifference(t *testing.T) {
tests := []map[string][]string{
map[string][]string{
"removeFrom": []string{"a", "b", "c"},
"stringsToRemove": []string{"b"},
"want": []string{"a", "c"},
},
map[string][]string{
"removeFrom": []string{"a", "b", "c"},
"stringsToRemove": []string{},
"want": []string{"a", "b", "c"},
},
map[string][]string{
"removeFrom": []string{},
"stringsToRemove": []string{"b"},
"want": []string{},
},
map[string][]string{
"removeFrom": []string{"a"},
"stringsToRemove": []string{"b"},
"want": []string{"a"},
},
}

for _, testCase := range tests {
assert.Equal(t, testCase["want"], sliceDifference(testCase["removeFrom"], testCase["stringsToRemove"]))
}
}
8 changes: 7 additions & 1 deletion cmd/golden/envhcl_allchilds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,13 @@ projects:
- ../terragrunt.hcl
- ../someRandomDir/terragrunt.hcl
dir: hcl_json/json_expanded
workflow: terragruntjson
workflow: terragruntjson
- autoplan:
enabled: false
when_modified:
- '*.hcl'
- '*.tf*'
dir: ignore_dependency/child
- autoplan:
enabled: false
when_modified:
Expand Down
8 changes: 7 additions & 1 deletion cmd/golden/envhcl_externalchilds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,13 @@ projects:
- ../terragrunt.hcl
- ../someRandomDir/terragrunt.hcl
dir: hcl_json/json_expanded
workflow: terragruntjson
workflow: terragruntjson
- autoplan:
enabled: false
when_modified:
- '*.hcl'
- '*.tf*'
dir: ignore_dependency/child
- autoplan:
enabled: false
when_modified:
Expand Down
11 changes: 11 additions & 0 deletions cmd/golden/ignore_dependencies.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
automerge: false
parallel_apply: true
parallel_plan: true
projects:
- autoplan:
enabled: false
when_modified:
- "*.hcl"
- "*.tf*"
dir: child
version: 3
17 changes: 17 additions & 0 deletions cmd/parse_locals.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ type ResolvedLocals struct {

// If set to true, create Atlantis project
markedProject *bool

// Dependencies to ignore
IgnoreAtlantisDependencies []string
}

// parseHcl uses the HCL2 parser to parse the given string into an HCL file body.
Expand Down Expand Up @@ -95,6 +98,8 @@ func mergeResolvedLocals(parent ResolvedLocals, child ResolvedLocals) ResolvedLo

parent.ExtraAtlantisDependencies = append(parent.ExtraAtlantisDependencies, child.ExtraAtlantisDependencies...)

parent.IgnoreAtlantisDependencies = append(parent.IgnoreAtlantisDependencies, child.IgnoreAtlantisDependencies...)

return parent
}

Expand Down Expand Up @@ -190,5 +195,17 @@ func resolveLocals(localsAsCty cty.Value) ResolvedLocals {
}
}

ignoreDependenciesAsCty, ok := rawLocals["ignore_atlantis_dependencies"]
if ok {
it := ignoreDependenciesAsCty.ElementIterator()
for it.Next() {
_, val := it.Element()
resolved.IgnoreAtlantisDependencies = append(
resolved.IgnoreAtlantisDependencies,
filepath.ToSlash(val.AsString()),
)
}
}

return resolved
}
2 changes: 1 addition & 1 deletion test_examples/extra_dependency/child/terragrunt.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ locals {
"some_extra_dep",
find_in_parent_folders("test_file.json")
]
}
}
15 changes: 15 additions & 0 deletions test_examples/ignore_dependency/child/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
terraform {
source = "git::[email protected]:transcend-io/terraform-aws-fargate-container?ref=v0.0.4"
}

dependency "ignore_me" {
config_path = find_in_parent_folders("ignore_me")
}

dependency "other_ignore_me" {
config_path = find_in_parent_folders("ignore_me")
}

locals {
ignore_atlantis_dependencies = ["${find_in_parent_folders("ignore_me")}/terragrunt.hcl", "other_ignore_me"]
}
3 changes: 3 additions & 0 deletions test_examples/ignore_dependency/ignore_me/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
fail = run_cmd("exit", "1")
}