From df259b27fb6163e4d2dbc53f70624b6f6e80c2b5 Mon Sep 17 00:00:00 2001 From: Veronika Gnilitska Date: Tue, 17 Dec 2024 10:00:59 -0500 Subject: [PATCH 1/4] fix: support more attributes --- README.md | 8 ++- .../spacelift-automation/stacks/example.yaml | 1 + main.tf | 62 +++++++++---------- outputs.tf | 14 +++++ variables.tf | 12 ++++ 5 files changed, 64 insertions(+), 33 deletions(-) create mode 100644 outputs.tf diff --git a/README.md b/README.md index df17afc..3d6f171 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ NOTE to Masterpoint team: We might want to create a small wrapper to automatize | Name | Version | | ------------------------------------------------------------------ | ------- | -| [spacelift](#provider_spacelift) | 1.16.1 | +| [spacelift](#provider_spacelift) | 1.19.0 | ## Modules @@ -174,7 +174,9 @@ NOTE to Masterpoint team: We might want to create a small wrapper to automatize | [drift_detection_schedule](#input_drift_detection_schedule) | The schedule for drift detection. | `list(string)` |
[
"0 4 * * *"
]
| no | | [drift_detection_timezone](#input_drift_detection_timezone) | The timezone for drift detection. | `string` | `"UTC"` | no | | [enable_local_preview](#input_enable_local_preview) | Indicates whether local preview runs can be triggered on this Stack. | `bool` | `false` | no | +| [enable_well_known_secret_masking](#input_enable_well_known_secret_masking) | Indicates whether well-known secret masking is enabled. | `bool` | `false` | no | | [enabled_root_modules](#input_enabled_root_modules) | List of root modules where to look for stack config files.
Ignored when all_root_modules_enabled is true.
Example: ["spacelift-automation", "k8s-cluster"] | `list(string)` | `[]` | no | +| [github_action_deploy](#input_github_action_deploy) | Indicates whether GitHub users can deploy from the Checks API. | `bool` | `true` | no | | [github_enterprise](#input_github_enterprise) | The GitHub VCS settings |
object({
namespace = string
id = optional(string)
})
| n/a | yes | | [manage_state](#input_manage_state) | Determines if Spacelift should manage state for this stack. | `bool` | `false` | no | | [protect_from_deletion](#input_protect_from_deletion) | Protect this stack from accidental deletion. If set, attempts to delete this stack will fail. | `bool` | `false` | no | @@ -188,7 +190,9 @@ NOTE to Masterpoint team: We might want to create a small wrapper to automatize ## Outputs -No outputs. +| Name | Description | +| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [spacelift_stacks](#output_spacelift_stacks) | A map of Spacelift stacks with selected attributes.
To reduce the risk of accidentally exporting sensitive data, only a subset of attributes is exported. | diff --git a/examples/complete/components/spacelift-automation/stacks/example.yaml b/examples/complete/components/spacelift-automation/stacks/example.yaml index 4b8bbc5..11bec8c 100644 --- a/examples/complete/components/spacelift-automation/stacks/example.yaml +++ b/examples/complete/components/spacelift-automation/stacks/example.yaml @@ -2,3 +2,4 @@ stack_settings: description: This Automation stack is used for Masterpoint's testing purposes labels: - stack_specific_label + drift_detection_enabled: true diff --git a/main.tf b/main.tf index 2b5a9b3..73808e3 100644 --- a/main.tf +++ b/main.tf @@ -234,36 +234,36 @@ module "deep" { resource "spacelift_stack" "default" { for_each = local.stacks - space_id = coalesce(try(local.stack_configs[each.key].space_id, null), var.space_id) - name = each.key - administrative = coalesce(try(local.stack_configs[each.key].administrative, null), var.administrative) - after_apply = compact(concat(try(local.stack_configs[each.key].after_apply, []), var.after_apply)) - after_destroy = compact(concat(try(local.stack_configs[each.key].after_destroy, []), var.after_destroy)) - after_init = compact(concat(try(local.stack_configs[each.key].after_init, []), var.after_init)) - after_perform = compact(concat(try(local.stack_configs[each.key].after_perform, []), var.after_perform)) - after_plan = compact(concat(try(local.stack_configs[each.key].after_plan, []), var.after_plan)) - autodeploy = coalesce(try(local.stack_configs[each.key].autodeploy, null), var.autodeploy) - autoretry = try(local.stack_configs[each.key].autoretry, var.autoretry) - before_apply = compact(coalesce(try(local.stack_configs[each.key].before_apply, []), var.before_apply)) - before_destroy = compact(coalesce(try(local.stack_configs[each.key].before_destroy, []), var.before_destroy)) - before_init = compact(coalesce(try(local.before_init[each.key], []), var.before_init)) - before_perform = compact(coalesce(try(local.stack_configs[each.key].before_perform, []), var.before_perform)) - before_plan = compact(coalesce(try(local.stack_configs[each.key].before_plan, []), var.before_plan)) - description = coalesce(try(local.stack_configs[each.key].description, null), var.description) - repository = try(local.stack_configs[each.key].repository, var.repository) - branch = try(local.stack_configs[each.key].branch, var.branch) - project_root = local.configs[each.key].project_root - manage_state = try(local.stack_configs[each.key].manage_state, var.manage_state) - labels = local.labels[each.key] - enable_local_preview = try(local.stack_configs[each.key].enable_local_preview, var.enable_local_preview) - terraform_smart_sanitization = try(local.stack_configs[each.key].terraform_smart_sanitization, var.terraform_smart_sanitization) - terraform_version = try(local.stack_configs[each.key].terraform_version, var.terraform_version) - terraform_workflow_tool = var.terraform_workflow_tool - terraform_workspace = local.configs[each.key].terraform_workspace - - protect_from_deletion = try(local.stack_configs[each.key].protect_from_deletion, var.protect_from_deletion) - - worker_pool_id = try(local.stack_configs[each.key].worker_pool_id, var.worker_pool_id) + administrative = coalesce(try(local.stack_configs[each.key].administrative, null), var.administrative) + after_apply = compact(concat(try(local.stack_configs[each.key].after_apply, []), var.after_apply)) + after_destroy = compact(concat(try(local.stack_configs[each.key].after_destroy, []), var.after_destroy)) + after_init = compact(concat(try(local.stack_configs[each.key].after_init, []), var.after_init)) + after_perform = compact(concat(try(local.stack_configs[each.key].after_perform, []), var.after_perform)) + after_plan = compact(concat(try(local.stack_configs[each.key].after_plan, []), var.after_plan)) + autodeploy = coalesce(try(local.stack_configs[each.key].autodeploy, null), var.autodeploy) + autoretry = try(local.stack_configs[each.key].autoretry, var.autoretry) + before_apply = compact(coalesce(try(local.stack_configs[each.key].before_apply, []), var.before_apply)) + before_destroy = compact(coalesce(try(local.stack_configs[each.key].before_destroy, []), var.before_destroy)) + before_init = compact(coalesce(try(local.before_init[each.key], []), var.before_init)) + before_perform = compact(coalesce(try(local.stack_configs[each.key].before_perform, []), var.before_perform)) + before_plan = compact(coalesce(try(local.stack_configs[each.key].before_plan, []), var.before_plan)) + branch = try(local.stack_configs[each.key].branch, var.branch) + description = coalesce(try(local.stack_configs[each.key].description, null), var.description) + enable_local_preview = try(local.stack_configs[each.key].enable_local_preview, var.enable_local_preview) + enable_well_known_secret_masking = try(local.stack_configs[each.key].enable_well_known_secret_masking, var.enable_well_known_secret_masking) + github_action_deploy = try(local.stack_configs[each.key].github_action_deploy, var.github_action_deploy) + labels = local.labels[each.key] + manage_state = try(local.stack_configs[each.key].manage_state, var.manage_state) + name = each.key + project_root = local.configs[each.key].project_root + protect_from_deletion = try(local.stack_configs[each.key].protect_from_deletion, var.protect_from_deletion) + repository = try(local.stack_configs[each.key].repository, var.repository) + space_id = coalesce(try(local.stack_configs[each.key].space_id, null), var.space_id) + terraform_smart_sanitization = try(local.stack_configs[each.key].terraform_smart_sanitization, var.terraform_smart_sanitization) + terraform_version = try(local.stack_configs[each.key].terraform_version, var.terraform_version) + terraform_workflow_tool = var.terraform_workflow_tool + terraform_workspace = local.configs[each.key].terraform_workspace + worker_pool_id = try(local.stack_configs[each.key].worker_pool_id, var.worker_pool_id) dynamic "github_enterprise" { for_each = var.github_enterprise != null ? [var.github_enterprise] : [] @@ -318,7 +318,7 @@ resource "spacelift_drift_detection" "default" { lifecycle { precondition { - condition = can(regex("^([0-9,\\-\\*]+\\s+){4}[0-9,\\-\\*]+$", try(local.stack_configs[each.key].drift_detection_schedule, var.drift_detection_schedule))) + condition = alltrue([for schedule in try(local.stack_configs[each.key].drift_detection_schedule, var.drift_detection_schedule) : can(regex("^([0-9,\\-\\*]+\\s+){4}[0-9,\\-\\*]+$", schedule))]) error_message = "Invalid cron schedule format for drift detection" } } diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..837e1c8 --- /dev/null +++ b/outputs.tf @@ -0,0 +1,14 @@ +output "spacelift_stacks" { + description = <<-EOT + A map of Spacelift stacks with selected attributes. + To reduce the risk of accidentally exporting sensitive data, only a subset of attributes is exported. + EOT + value = { + for name, stack in spacelift_stack.default : name => { + id = stack.id + labels = stack.labels + autodeploy = stack.autodeploy + administrative = stack.administrative + } + } +} diff --git a/variables.tf b/variables.tf index 801c1db..0a8c1f7 100644 --- a/variables.tf +++ b/variables.tf @@ -214,8 +214,20 @@ variable "enable_local_preview" { type = bool description = "Indicates whether local preview runs can be triggered on this Stack." default = false +} + +variable "enable_well_known_secret_masking" { + type = bool + description = "Indicates whether well-known secret masking is enabled." + default = false +} +variable "github_action_deploy" { + type = bool + description = "Indicates whether GitHub users can deploy from the Checks API." + default = true } + variable "manage_state" { type = bool description = "Determines if Spacelift should manage state for this stack." From 29862829a8fe375a5ef6b46de7e11b5bcbf5d508 Mon Sep 17 00:00:00 2001 From: Veronika Gnilitska Date: Wed, 18 Dec 2024 05:29:57 -0500 Subject: [PATCH 2/4] chore: enable well-known secret masking by default --- README.md | 2 +- variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3d6f171..910c25f 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ NOTE to Masterpoint team: We might want to create a small wrapper to automatize | [drift_detection_schedule](#input_drift_detection_schedule) | The schedule for drift detection. | `list(string)` |
[
"0 4 * * *"
]
| no | | [drift_detection_timezone](#input_drift_detection_timezone) | The timezone for drift detection. | `string` | `"UTC"` | no | | [enable_local_preview](#input_enable_local_preview) | Indicates whether local preview runs can be triggered on this Stack. | `bool` | `false` | no | -| [enable_well_known_secret_masking](#input_enable_well_known_secret_masking) | Indicates whether well-known secret masking is enabled. | `bool` | `false` | no | +| [enable_well_known_secret_masking](#input_enable_well_known_secret_masking) | Indicates whether well-known secret masking is enabled. | `bool` | `true` | no | | [enabled_root_modules](#input_enabled_root_modules) | List of root modules where to look for stack config files.
Ignored when all_root_modules_enabled is true.
Example: ["spacelift-automation", "k8s-cluster"] | `list(string)` | `[]` | no | | [github_action_deploy](#input_github_action_deploy) | Indicates whether GitHub users can deploy from the Checks API. | `bool` | `true` | no | | [github_enterprise](#input_github_enterprise) | The GitHub VCS settings |
object({
namespace = string
id = optional(string)
})
| n/a | yes | diff --git a/variables.tf b/variables.tf index 0a8c1f7..03d09c9 100644 --- a/variables.tf +++ b/variables.tf @@ -219,7 +219,7 @@ variable "enable_local_preview" { variable "enable_well_known_secret_masking" { type = bool description = "Indicates whether well-known secret masking is enabled." - default = false + default = true } variable "github_action_deploy" { From 8ccba9fb41791f0c8ba31b30fb20e89dd77360e4 Mon Sep 17 00:00:00 2001 From: Veronika Gnilitska Date: Wed, 18 Dec 2024 11:07:35 -0500 Subject: [PATCH 3/4] feat: allow TF workspace usage --- README.md | 87 ++++++++++--------- .../components/random-pet/stacks/example.yaml | 2 + main.tf | 9 +- variables.tf | 12 +++ 4 files changed, 64 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 910c25f..1d9d7bf 100644 --- a/README.md +++ b/README.md @@ -144,49 +144,50 @@ NOTE to Masterpoint team: We might want to create a small wrapper to automatize ## Inputs -| Name | Description | Type | Default | Required | -| --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------- | :------: | -| [administrative](#input_administrative) | Flag to mark the stack as administrative | `bool` | `false` | no | -| [after_apply](#input_after_apply) | List of after-apply scripts | `list(string)` | `[]` | no | -| [after_destroy](#input_after_destroy) | List of after-destroy scripts | `list(string)` | `[]` | no | -| [after_init](#input_after_init) | List of after-init scripts | `list(string)` | `[]` | no | -| [after_perform](#input_after_perform) | List of after-perform scripts | `list(string)` | `[]` | no | -| [after_plan](#input_after_plan) | List of after-plan scripts | `list(string)` | `[]` | no | -| [all_root_modules_enabled](#input_all_root_modules_enabled) | When set to true, all subdirectories in root_modules_path will be treated as root modules. | `bool` | `false` | no | -| [autodeploy](#input_autodeploy) | Flag to enable/disable automatic deployment of the stack | `bool` | `true` | no | -| [autoretry](#input_autoretry) | Flag to enable/disable automatic retry of the stack | `bool` | `false` | no | -| [aws_integration_attachment_read](#input_aws_integration_attachment_read) | Indicates whether this attachment is used for read operations. | `bool` | `true` | no | -| [aws_integration_attachment_write](#input_aws_integration_attachment_write) | Indicates whether this attachment is used for write operations. | `bool` | `true` | no | -| [aws_integration_enabled](#input_aws_integration_enabled) | Indicates whether the AWS integration is enabled. | `bool` | `false` | no | -| [aws_integration_id](#input_aws_integration_id) | ID of the AWS integration to attach. | `string` | `null` | no | -| [before_apply](#input_before_apply) | List of before-apply scripts | `list(string)` | `[]` | no | -| [before_destroy](#input_before_destroy) | List of before-destroy scripts | `list(string)` | `[]` | no | -| [before_init](#input_before_init) | List of before-init scripts | `list(string)` | `[]` | no | -| [before_perform](#input_before_perform) | List of before-perform scripts | `list(string)` | `[]` | no | -| [before_plan](#input_before_plan) | List of before-plan scripts | `list(string)` | `[]` | no | -| [branch](#input_branch) | Specify which branch to use within the infrastructure repository. | `string` | `"main"` | no | -| [common_config_file](#input_common_config_file) | Name of the common configuration file for the stack across a root module. | `string` | `"common.yaml"` | no | -| [description](#input_description) | Description of the stack | `string` | `"Managed by spacelift-automation Terraform root module."` | no | -| [destructor_enabled](#input_destructor_enabled) | Flag to enable/disable the destructor for the Stack. | `bool` | `false` | no | -| [drift_detection_enabled](#input_drift_detection_enabled) | Flag to enable/disable Drift Detection configuration for a Stack. | `bool` | `false` | no | -| [drift_detection_ignore_state](#input_drift_detection_ignore_state) | Controls whether drift detection should be performed on a stack
in any final state instead of just 'Finished'. | `bool` | `false` | no | -| [drift_detection_reconcile](#input_drift_detection_reconcile) | Flag to enable/disable automatic reconciliation of drifts. | `bool` | `false` | no | -| [drift_detection_schedule](#input_drift_detection_schedule) | The schedule for drift detection. | `list(string)` |
[
"0 4 * * *"
]
| no | -| [drift_detection_timezone](#input_drift_detection_timezone) | The timezone for drift detection. | `string` | `"UTC"` | no | -| [enable_local_preview](#input_enable_local_preview) | Indicates whether local preview runs can be triggered on this Stack. | `bool` | `false` | no | -| [enable_well_known_secret_masking](#input_enable_well_known_secret_masking) | Indicates whether well-known secret masking is enabled. | `bool` | `true` | no | -| [enabled_root_modules](#input_enabled_root_modules) | List of root modules where to look for stack config files.
Ignored when all_root_modules_enabled is true.
Example: ["spacelift-automation", "k8s-cluster"] | `list(string)` | `[]` | no | -| [github_action_deploy](#input_github_action_deploy) | Indicates whether GitHub users can deploy from the Checks API. | `bool` | `true` | no | -| [github_enterprise](#input_github_enterprise) | The GitHub VCS settings |
object({
namespace = string
id = optional(string)
})
| n/a | yes | -| [manage_state](#input_manage_state) | Determines if Spacelift should manage state for this stack. | `bool` | `false` | no | -| [protect_from_deletion](#input_protect_from_deletion) | Protect this stack from accidental deletion. If set, attempts to delete this stack will fail. | `bool` | `false` | no | -| [repository](#input_repository) | The name of your infrastructure repo | `string` | n/a | yes | -| [root_modules_path](#input_root_modules_path) | The path, relative to the root of the repository, where the root module can be found. | `string` | `"root-modules"` | no | -| [space_id](#input_space_id) | Place the stack in the specified space_id. | `string` | `"root"` | no | -| [terraform_smart_sanitization](#input_terraform_smart_sanitization) | Indicates whether runs on this will use terraform's sensitive value system to sanitize
the outputs of Terraform state and plans in spacelift instead of sanitizing all fields. | `bool` | `false` | no | -| [terraform_version](#input_terraform_version) | Terraform version to use. | `string` | `"1.7.2"` | no | -| [terraform_workflow_tool](#input_terraform_workflow_tool) | Defines the tool that will be used to execute the workflow.
This can be one of OPEN_TOFU, TERRAFORM_FOSS or CUSTOM. | `string` | `"OPEN_TOFU"` | no | -| [worker_pool_id](#input_worker_pool_id) | ID of the worker pool to use.
NOTE: worker_pool_id is required when using a self-hosted instance of Spacelift. | `string` | `null` | no | +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------- | :------: | +| [administrative](#input_administrative) | Flag to mark the stack as administrative | `bool` | `false` | no | +| [after_apply](#input_after_apply) | List of after-apply scripts | `list(string)` | `[]` | no | +| [after_destroy](#input_after_destroy) | List of after-destroy scripts | `list(string)` | `[]` | no | +| [after_init](#input_after_init) | List of after-init scripts | `list(string)` | `[]` | no | +| [after_perform](#input_after_perform) | List of after-perform scripts | `list(string)` | `[]` | no | +| [after_plan](#input_after_plan) | List of after-plan scripts | `list(string)` | `[]` | no | +| [all_root_modules_enabled](#input_all_root_modules_enabled) | When set to true, all subdirectories in root_modules_path will be treated as root modules. | `bool` | `false` | no | +| [autodeploy](#input_autodeploy) | Flag to enable/disable automatic deployment of the stack | `bool` | `true` | no | +| [autoretry](#input_autoretry) | Flag to enable/disable automatic retry of the stack | `bool` | `false` | no | +| [aws_integration_attachment_read](#input_aws_integration_attachment_read) | Indicates whether this attachment is used for read operations. | `bool` | `true` | no | +| [aws_integration_attachment_write](#input_aws_integration_attachment_write) | Indicates whether this attachment is used for write operations. | `bool` | `true` | no | +| [aws_integration_enabled](#input_aws_integration_enabled) | Indicates whether the AWS integration is enabled. | `bool` | `false` | no | +| [aws_integration_id](#input_aws_integration_id) | ID of the AWS integration to attach. | `string` | `null` | no | +| [before_apply](#input_before_apply) | List of before-apply scripts | `list(string)` | `[]` | no | +| [before_destroy](#input_before_destroy) | List of before-destroy scripts | `list(string)` | `[]` | no | +| [before_init](#input_before_init) | List of before-init scripts | `list(string)` | `[]` | no | +| [before_perform](#input_before_perform) | List of before-perform scripts | `list(string)` | `[]` | no | +| [before_plan](#input_before_plan) | List of before-plan scripts | `list(string)` | `[]` | no | +| [branch](#input_branch) | Specify which branch to use within the infrastructure repository. | `string` | `"main"` | no | +| [common_config_file](#input_common_config_file) | Name of the common configuration file for the stack across a root module. | `string` | `"common.yaml"` | no | +| [default_tf_workspace_enabled](#input_default_tf_workspace_enabled) | Enables the use of `default` Terraform workspace instead of managing multiple workspaces within a root module.

NOTE: We encourage the use of Terraform workspaces to manage multiple environments. However, in some cases,
you may want to disable this behavior. This is particularly useful when integrating this module
into an existing (brownfield) infrastructure setup. | `bool` | `false` | no | +| [description](#input_description) | Description of the stack | `string` | `"Managed by spacelift-automation Terraform root module."` | no | +| [destructor_enabled](#input_destructor_enabled) | Flag to enable/disable the destructor for the Stack. | `bool` | `false` | no | +| [drift_detection_enabled](#input_drift_detection_enabled) | Flag to enable/disable Drift Detection configuration for a Stack. | `bool` | `false` | no | +| [drift_detection_ignore_state](#input_drift_detection_ignore_state) | Controls whether drift detection should be performed on a stack
in any final state instead of just 'Finished'. | `bool` | `false` | no | +| [drift_detection_reconcile](#input_drift_detection_reconcile) | Flag to enable/disable automatic reconciliation of drifts. | `bool` | `false` | no | +| [drift_detection_schedule](#input_drift_detection_schedule) | The schedule for drift detection. | `list(string)` |
[
"0 4 * * *"
]
| no | +| [drift_detection_timezone](#input_drift_detection_timezone) | The timezone for drift detection. | `string` | `"UTC"` | no | +| [enable_local_preview](#input_enable_local_preview) | Indicates whether local preview runs can be triggered on this Stack. | `bool` | `false` | no | +| [enable_well_known_secret_masking](#input_enable_well_known_secret_masking) | Indicates whether well-known secret masking is enabled. | `bool` | `true` | no | +| [enabled_root_modules](#input_enabled_root_modules) | List of root modules where to look for stack config files.
Ignored when all_root_modules_enabled is true.
Example: ["spacelift-automation", "k8s-cluster"] | `list(string)` | `[]` | no | +| [github_action_deploy](#input_github_action_deploy) | Indicates whether GitHub users can deploy from the Checks API. | `bool` | `true` | no | +| [github_enterprise](#input_github_enterprise) | The GitHub VCS settings |
object({
namespace = string
id = optional(string)
})
| n/a | yes | +| [manage_state](#input_manage_state) | Determines if Spacelift should manage state for this stack. | `bool` | `false` | no | +| [protect_from_deletion](#input_protect_from_deletion) | Protect this stack from accidental deletion. If set, attempts to delete this stack will fail. | `bool` | `false` | no | +| [repository](#input_repository) | The name of your infrastructure repo | `string` | n/a | yes | +| [root_modules_path](#input_root_modules_path) | The path, relative to the root of the repository, where the root module can be found. | `string` | `"root-modules"` | no | +| [space_id](#input_space_id) | Place the stack in the specified space_id. | `string` | `"root"` | no | +| [terraform_smart_sanitization](#input_terraform_smart_sanitization) | Indicates whether runs on this will use terraform's sensitive value system to sanitize
the outputs of Terraform state and plans in spacelift instead of sanitizing all fields. | `bool` | `false` | no | +| [terraform_version](#input_terraform_version) | Terraform version to use. | `string` | `"1.7.2"` | no | +| [terraform_workflow_tool](#input_terraform_workflow_tool) | Defines the tool that will be used to execute the workflow.
This can be one of OPEN_TOFU, TERRAFORM_FOSS or CUSTOM. | `string` | `"OPEN_TOFU"` | no | +| [worker_pool_id](#input_worker_pool_id) | ID of the worker pool to use.
NOTE: worker_pool_id is required when using a self-hosted instance of Spacelift. | `string` | `null` | no | ## Outputs diff --git a/examples/complete/components/random-pet/stacks/example.yaml b/examples/complete/components/random-pet/stacks/example.yaml index 39391c6..a47acac 100644 --- a/examples/complete/components/random-pet/stacks/example.yaml +++ b/examples/complete/components/random-pet/stacks/example.yaml @@ -1,2 +1,4 @@ stack_settings: manage_state: true + +default_tf_workspace_enabled: true diff --git a/main.tf b/main.tf index 73808e3..2a6cd2e 100644 --- a/main.tf +++ b/main.tf @@ -102,7 +102,10 @@ locals { { "project_root" = replace(format("%s/%s", var.root_modules_path, module), "../", "") "root_module" = module, - "terraform_workspace" = trimsuffix(file, ".yaml"), + "terraform_workspace" = try(content.default_tf_workspace_enabled, var.default_tf_workspace_enabled) ? "default" : trimsuffix(file, ".yaml"), + # `yaml` is intentionally used here as we require Stack and `tfvars` config files to be named equally + # TODO: Add tests to ensure that the `tfvars` file is named the same as the Stack config file + "tfvars_file_name" = trimsuffix(file, ".yaml"), }, content ) if file != var.common_config_file @@ -183,7 +186,7 @@ locals { _folder_labels = { for stack in local.stacks : stack => [ - "folder:${local.configs[stack].root_module}/${local.configs[stack].terraform_workspace}" + "folder:${local.configs[stack].root_module}/${local.configs[stack].tfvars_file_name}" ] } @@ -214,7 +217,7 @@ locals { # This command is required for each stack. # It copies the tfvars file from the stack's workspace to the root module's directory # and renames it to `spacelift.auto.tfvars` to automatically load variable definitions for each run/task. - ["cp tfvars/${local.configs[stack].terraform_workspace}.tfvars spacelift.auto.tfvars"], + ["cp tfvars/${local.configs[stack].tfvars_file_name}.tfvars spacelift.auto.tfvars"], )) if try(local.configs[stack].tfvars.enabled, true) } } diff --git a/variables.tf b/variables.tf index 03d09c9..c205cf5 100644 --- a/variables.tf +++ b/variables.tf @@ -165,6 +165,18 @@ variable "before_plan" { default = [] } +variable "default_tf_workspace_enabled" { + type = bool + default = false + description = <<-EOT + Enables the use of `default` Terraform workspace instead of managing multiple workspaces within a root module. + + NOTE: We encourage the use of Terraform workspaces to manage multiple environments. However, in some cases, + you may want to disable this behavior. This is particularly useful when integrating this module + into an existing (brownfield) infrastructure setup. + EOT +} + variable "description" { type = string description = "Description of the stack" From b02370bcb2cf28411d53e7255d85791b393bd624 Mon Sep 17 00:00:00 2001 From: Veronika Gnilitska Date: Wed, 18 Dec 2024 13:30:51 -0500 Subject: [PATCH 4/4] chore: adds precondition + addressess PR feedback --- README.md | 88 +++++++++---------- .../components/random-pet/stacks/common.yaml | 2 + .../components/random-pet/stacks/example.yaml | 3 +- main.tf | 15 ++++ variables.tf | 6 +- 5 files changed, 66 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 1d9d7bf..91b3c1b 100644 --- a/README.md +++ b/README.md @@ -144,50 +144,50 @@ NOTE to Masterpoint team: We might want to create a small wrapper to automatize ## Inputs -| Name | Description | Type | Default | Required | -| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------- | :------: | -| [administrative](#input_administrative) | Flag to mark the stack as administrative | `bool` | `false` | no | -| [after_apply](#input_after_apply) | List of after-apply scripts | `list(string)` | `[]` | no | -| [after_destroy](#input_after_destroy) | List of after-destroy scripts | `list(string)` | `[]` | no | -| [after_init](#input_after_init) | List of after-init scripts | `list(string)` | `[]` | no | -| [after_perform](#input_after_perform) | List of after-perform scripts | `list(string)` | `[]` | no | -| [after_plan](#input_after_plan) | List of after-plan scripts | `list(string)` | `[]` | no | -| [all_root_modules_enabled](#input_all_root_modules_enabled) | When set to true, all subdirectories in root_modules_path will be treated as root modules. | `bool` | `false` | no | -| [autodeploy](#input_autodeploy) | Flag to enable/disable automatic deployment of the stack | `bool` | `true` | no | -| [autoretry](#input_autoretry) | Flag to enable/disable automatic retry of the stack | `bool` | `false` | no | -| [aws_integration_attachment_read](#input_aws_integration_attachment_read) | Indicates whether this attachment is used for read operations. | `bool` | `true` | no | -| [aws_integration_attachment_write](#input_aws_integration_attachment_write) | Indicates whether this attachment is used for write operations. | `bool` | `true` | no | -| [aws_integration_enabled](#input_aws_integration_enabled) | Indicates whether the AWS integration is enabled. | `bool` | `false` | no | -| [aws_integration_id](#input_aws_integration_id) | ID of the AWS integration to attach. | `string` | `null` | no | -| [before_apply](#input_before_apply) | List of before-apply scripts | `list(string)` | `[]` | no | -| [before_destroy](#input_before_destroy) | List of before-destroy scripts | `list(string)` | `[]` | no | -| [before_init](#input_before_init) | List of before-init scripts | `list(string)` | `[]` | no | -| [before_perform](#input_before_perform) | List of before-perform scripts | `list(string)` | `[]` | no | -| [before_plan](#input_before_plan) | List of before-plan scripts | `list(string)` | `[]` | no | -| [branch](#input_branch) | Specify which branch to use within the infrastructure repository. | `string` | `"main"` | no | -| [common_config_file](#input_common_config_file) | Name of the common configuration file for the stack across a root module. | `string` | `"common.yaml"` | no | -| [default_tf_workspace_enabled](#input_default_tf_workspace_enabled) | Enables the use of `default` Terraform workspace instead of managing multiple workspaces within a root module.

NOTE: We encourage the use of Terraform workspaces to manage multiple environments. However, in some cases,
you may want to disable this behavior. This is particularly useful when integrating this module
into an existing (brownfield) infrastructure setup. | `bool` | `false` | no | -| [description](#input_description) | Description of the stack | `string` | `"Managed by spacelift-automation Terraform root module."` | no | -| [destructor_enabled](#input_destructor_enabled) | Flag to enable/disable the destructor for the Stack. | `bool` | `false` | no | -| [drift_detection_enabled](#input_drift_detection_enabled) | Flag to enable/disable Drift Detection configuration for a Stack. | `bool` | `false` | no | -| [drift_detection_ignore_state](#input_drift_detection_ignore_state) | Controls whether drift detection should be performed on a stack
in any final state instead of just 'Finished'. | `bool` | `false` | no | -| [drift_detection_reconcile](#input_drift_detection_reconcile) | Flag to enable/disable automatic reconciliation of drifts. | `bool` | `false` | no | -| [drift_detection_schedule](#input_drift_detection_schedule) | The schedule for drift detection. | `list(string)` |
[
"0 4 * * *"
]
| no | -| [drift_detection_timezone](#input_drift_detection_timezone) | The timezone for drift detection. | `string` | `"UTC"` | no | -| [enable_local_preview](#input_enable_local_preview) | Indicates whether local preview runs can be triggered on this Stack. | `bool` | `false` | no | -| [enable_well_known_secret_masking](#input_enable_well_known_secret_masking) | Indicates whether well-known secret masking is enabled. | `bool` | `true` | no | -| [enabled_root_modules](#input_enabled_root_modules) | List of root modules where to look for stack config files.
Ignored when all_root_modules_enabled is true.
Example: ["spacelift-automation", "k8s-cluster"] | `list(string)` | `[]` | no | -| [github_action_deploy](#input_github_action_deploy) | Indicates whether GitHub users can deploy from the Checks API. | `bool` | `true` | no | -| [github_enterprise](#input_github_enterprise) | The GitHub VCS settings |
object({
namespace = string
id = optional(string)
})
| n/a | yes | -| [manage_state](#input_manage_state) | Determines if Spacelift should manage state for this stack. | `bool` | `false` | no | -| [protect_from_deletion](#input_protect_from_deletion) | Protect this stack from accidental deletion. If set, attempts to delete this stack will fail. | `bool` | `false` | no | -| [repository](#input_repository) | The name of your infrastructure repo | `string` | n/a | yes | -| [root_modules_path](#input_root_modules_path) | The path, relative to the root of the repository, where the root module can be found. | `string` | `"root-modules"` | no | -| [space_id](#input_space_id) | Place the stack in the specified space_id. | `string` | `"root"` | no | -| [terraform_smart_sanitization](#input_terraform_smart_sanitization) | Indicates whether runs on this will use terraform's sensitive value system to sanitize
the outputs of Terraform state and plans in spacelift instead of sanitizing all fields. | `bool` | `false` | no | -| [terraform_version](#input_terraform_version) | Terraform version to use. | `string` | `"1.7.2"` | no | -| [terraform_workflow_tool](#input_terraform_workflow_tool) | Defines the tool that will be used to execute the workflow.
This can be one of OPEN_TOFU, TERRAFORM_FOSS or CUSTOM. | `string` | `"OPEN_TOFU"` | no | -| [worker_pool_id](#input_worker_pool_id) | ID of the worker pool to use.
NOTE: worker_pool_id is required when using a self-hosted instance of Spacelift. | `string` | `null` | no | +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------- | :------: | +| [administrative](#input_administrative) | Flag to mark the stack as administrative | `bool` | `false` | no | +| [after_apply](#input_after_apply) | List of after-apply scripts | `list(string)` | `[]` | no | +| [after_destroy](#input_after_destroy) | List of after-destroy scripts | `list(string)` | `[]` | no | +| [after_init](#input_after_init) | List of after-init scripts | `list(string)` | `[]` | no | +| [after_perform](#input_after_perform) | List of after-perform scripts | `list(string)` | `[]` | no | +| [after_plan](#input_after_plan) | List of after-plan scripts | `list(string)` | `[]` | no | +| [all_root_modules_enabled](#input_all_root_modules_enabled) | When set to true, all subdirectories in root_modules_path will be treated as root modules. | `bool` | `false` | no | +| [autodeploy](#input_autodeploy) | Flag to enable/disable automatic deployment of the stack | `bool` | `true` | no | +| [autoretry](#input_autoretry) | Flag to enable/disable automatic retry of the stack | `bool` | `false` | no | +| [aws_integration_attachment_read](#input_aws_integration_attachment_read) | Indicates whether this attachment is used for read operations. | `bool` | `true` | no | +| [aws_integration_attachment_write](#input_aws_integration_attachment_write) | Indicates whether this attachment is used for write operations. | `bool` | `true` | no | +| [aws_integration_enabled](#input_aws_integration_enabled) | Indicates whether the AWS integration is enabled. | `bool` | `false` | no | +| [aws_integration_id](#input_aws_integration_id) | ID of the AWS integration to attach. | `string` | `null` | no | +| [before_apply](#input_before_apply) | List of before-apply scripts | `list(string)` | `[]` | no | +| [before_destroy](#input_before_destroy) | List of before-destroy scripts | `list(string)` | `[]` | no | +| [before_init](#input_before_init) | List of before-init scripts | `list(string)` | `[]` | no | +| [before_perform](#input_before_perform) | List of before-perform scripts | `list(string)` | `[]` | no | +| [before_plan](#input_before_plan) | List of before-plan scripts | `list(string)` | `[]` | no | +| [branch](#input_branch) | Specify which branch to use within the infrastructure repository. | `string` | `"main"` | no | +| [common_config_file](#input_common_config_file) | Name of the common configuration file for the stack across a root module. | `string` | `"common.yaml"` | no | +| [default_tf_workspace_enabled](#input_default_tf_workspace_enabled) | Enables the use of `default` Terraform workspace instead of managing multiple workspaces within a root module.

NOTE: We encourage the use of Terraform workspaces to manage multiple environments.
However, you will want to disable this behavior if you're utilizing different backends for each instance
of your root modules (we call this "Dynamic Backends"). | `bool` | `false` | no | +| [description](#input_description) | Description of the stack | `string` | `"Managed by spacelift-automation Terraform root module."` | no | +| [destructor_enabled](#input_destructor_enabled) | Flag to enable/disable the destructor for the Stack. | `bool` | `false` | no | +| [drift_detection_enabled](#input_drift_detection_enabled) | Flag to enable/disable Drift Detection configuration for a Stack. | `bool` | `false` | no | +| [drift_detection_ignore_state](#input_drift_detection_ignore_state) | Controls whether drift detection should be performed on a stack
in any final state instead of just 'Finished'. | `bool` | `false` | no | +| [drift_detection_reconcile](#input_drift_detection_reconcile) | Flag to enable/disable automatic reconciliation of drifts. | `bool` | `false` | no | +| [drift_detection_schedule](#input_drift_detection_schedule) | The schedule for drift detection. | `list(string)` |
[
"0 4 * * *"
]
| no | +| [drift_detection_timezone](#input_drift_detection_timezone) | The timezone for drift detection. | `string` | `"UTC"` | no | +| [enable_local_preview](#input_enable_local_preview) | Indicates whether local preview runs can be triggered on this Stack. | `bool` | `false` | no | +| [enable_well_known_secret_masking](#input_enable_well_known_secret_masking) | Indicates whether well-known secret masking is enabled. | `bool` | `true` | no | +| [enabled_root_modules](#input_enabled_root_modules) | List of root modules where to look for stack config files.
Ignored when all_root_modules_enabled is true.
Example: ["spacelift-automation", "k8s-cluster"] | `list(string)` | `[]` | no | +| [github_action_deploy](#input_github_action_deploy) | Indicates whether GitHub users can deploy from the Checks API. | `bool` | `true` | no | +| [github_enterprise](#input_github_enterprise) | The GitHub VCS settings |
object({
namespace = string
id = optional(string)
})
| n/a | yes | +| [manage_state](#input_manage_state) | Determines if Spacelift should manage state for this stack. | `bool` | `false` | no | +| [protect_from_deletion](#input_protect_from_deletion) | Protect this stack from accidental deletion. If set, attempts to delete this stack will fail. | `bool` | `false` | no | +| [repository](#input_repository) | The name of your infrastructure repo | `string` | n/a | yes | +| [root_modules_path](#input_root_modules_path) | The path, relative to the root of the repository, where the root module can be found. | `string` | `"root-modules"` | no | +| [space_id](#input_space_id) | Place the stack in the specified space_id. | `string` | `"root"` | no | +| [terraform_smart_sanitization](#input_terraform_smart_sanitization) | Indicates whether runs on this will use terraform's sensitive value system to sanitize
the outputs of Terraform state and plans in spacelift instead of sanitizing all fields. | `bool` | `false` | no | +| [terraform_version](#input_terraform_version) | Terraform version to use. | `string` | `"1.7.2"` | no | +| [terraform_workflow_tool](#input_terraform_workflow_tool) | Defines the tool that will be used to execute the workflow.
This can be one of OPEN_TOFU, TERRAFORM_FOSS or CUSTOM. | `string` | `"OPEN_TOFU"` | no | +| [worker_pool_id](#input_worker_pool_id) | ID of the worker pool to use.
NOTE: worker_pool_id is required when using a self-hosted instance of Spacelift. | `string` | `null` | no | ## Outputs diff --git a/examples/complete/components/random-pet/stacks/common.yaml b/examples/complete/components/random-pet/stacks/common.yaml index 5cdd375..e640853 100644 --- a/examples/complete/components/random-pet/stacks/common.yaml +++ b/examples/complete/components/random-pet/stacks/common.yaml @@ -1,3 +1,5 @@ stack_settings: manage_state: true description: This stack generates random pet names + labels: + - common_label diff --git a/examples/complete/components/random-pet/stacks/example.yaml b/examples/complete/components/random-pet/stacks/example.yaml index a47acac..8ecded4 100644 --- a/examples/complete/components/random-pet/stacks/example.yaml +++ b/examples/complete/components/random-pet/stacks/example.yaml @@ -1,4 +1,5 @@ stack_settings: manage_state: true - + labels: + - stack_specific_label default_tf_workspace_enabled: true diff --git a/main.tf b/main.tf index 2a6cd2e..7117a8c 100644 --- a/main.tf +++ b/main.tf @@ -274,6 +274,21 @@ resource "spacelift_stack" "default" { namespace = github_enterprise.value["namespace"] } } + + lifecycle { + # Expected `tfvars` file exists + precondition { + condition = fileexists("${local.configs[each.key].project_root}/tfvars/${local.configs[each.key].tfvars_file_name}.tfvars") + error_message = <<-EOT + The required .tfvars file is missing for stack "${each.key}". + + Expected location: + "${local.configs[each.key].project_root}/tfvars/${local.configs[each.key].tfvars_file_name}.tfvars" + + Ensure that the specified .tfvars file exists in the expected path and try again. + EOT + } + } } # The Spacelift Destructor is a feature designed to automatically clean up the resources no longer managed by our IaC. diff --git a/variables.tf b/variables.tf index c205cf5..ddcb2fd 100644 --- a/variables.tf +++ b/variables.tf @@ -171,9 +171,9 @@ variable "default_tf_workspace_enabled" { description = <<-EOT Enables the use of `default` Terraform workspace instead of managing multiple workspaces within a root module. - NOTE: We encourage the use of Terraform workspaces to manage multiple environments. However, in some cases, - you may want to disable this behavior. This is particularly useful when integrating this module - into an existing (brownfield) infrastructure setup. + NOTE: We encourage the use of Terraform workspaces to manage multiple environments. + However, you will want to disable this behavior if you're utilizing different backends for each instance + of your root modules (we call this "Dynamic Backends"). EOT }