Home

Awesome

spacelift-automation

Release

This Terraform child module provides infrastructure automation for projects in Spacelift.

Overview

The spacelift-automation root module is designed to streamline the deployment and management of all Spacelift infrastructure, including itself.

It automates the creation of "child" stacks and all the required accompanying Spacelift resources. For each enabled root module it creates:

  1. Spacelift Stack You can think about a stack as a combination of source code, state file and configuration in the form of environment variables and mounted files.
  2. Spacelift Stack Destructor Required to destroy the resources of a Stack before deleting it. Destroying this resource will delete the resources in the stack. If this resource needs to be deleted and the resources in the stacks are to be preserved, ensure that the deactivated attribute is set to true.
  3. Spacelift AWS Integration Attachment Associates a specific AWS IAM role with a stack to allow it to assume that role. The IAM role typically has permissions to manage specific AWS resources, and Spacelift assumes this role to run the operations required by the stack.
  4. Spacelift Initialization Hook Prepares your environment before executing infrastructure code. This custom script copies corresponding Terraform tfvars files into a working directory before either run or task as a spacelift.auto.tfvars file. It's automatically loaded into the OpenTofu/Terraform execution environment.

Usage

Spacelift Automation logic is opinionated and heavily relies on the Git repository structure. This module is configured to track all the files in the provided root module directory and create the stack based on the provided configuration (if any).

Structure requirements are:

Let's check the example. Input repo structure:

├── root-modules
│   ├── spacelift-aws-role
│   │   ├── stacks
│   │   │   └── dev.yaml
│   │   │   └── stage.yaml
│   │   │   └── common.yaml
│   │   ├── tfvars
│   │   │   └── dev.tfvars
│   │   │   └── stage.tfvars
│   │   ├── variables.tf
│   │   └── versions.tf
│   ├── k8s-cluster
│   │   ├── stacks
│   │   │   └── dev.yaml
│   │   │   └── prod.yaml
│   │   │   └── common.yaml
│   │   ├── tfvars
│   │   │   └── dev.tfvars
│   │   │   └── prod.tfvars
│   │   ├── variables.tf
│   │   ├── main.tf
│   │   └── versions.tf
...

Root module inputs:

aws_integration_id = "ZDPP8SKNVG0G27T4"

# GitHub configuration
github_enterprise = {
  namespace = "masterpointio"
}
repository = "terraform-spacelift-automation"

# Stacks configurations
root_modules_path    = "root-modules"
enabled_root_modules = ["spacelift-aws-role"]

The configuration above creates the following stacks:

These stacks have the following configuration:

FAQs

Why are variable values provided separately in tfvars/ and not in the yaml file?

This is to support easy local and outside-spacelift operations. Keeping variable values in a tfvars file per workspace allows you to simply pass that file to the relevant CLI command locally via the -var-file option so that you don't need to provide values individually.

Can I create a Spacelift Stack for Spacelift Automation? (Recommended)

Spacelift Automation can manage itself as a Stack as well, and we recommend this so you can fully automate your Stack management upon merging to your given branch. Follow these next steps to achieve that:

  1. Create a new vanilla OpenTofu/Terraform root module that consumes this child module and supplies the necessary configuration for your unique setup. In other words, it's a configuration that uses the default capabilities of either OpenTofu or Terraform without any customization, or third-party tools or plugins.
  2. Optionally, create a Terraform workspace that will be used for your Automation configuration, e.g.:
    tofu workspace new masterpoint
    
    Remember that Stack config and tfvars file name must be equal to the workspace, which can be default.
  3. Apply the vanilla OpenTofu/Terraform configuration.
  4. Move the Automation configs to the <root-modules>/spacelift-automation/stacks directory and push the changes to the tracked repo and branch.
  5. From this moment, Spacelift Automation is tracking the changes to its Stack configs and Terraform variables.

Check out an example of such a configuration in the examples/complete.

NOTE to Masterpoint team: We might want to create a small wrapper to automatize this using Taskit. On hold for now.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

Requirements

NameVersion
<a name="requirement_terraform"></a> terraform>= 1.6
<a name="requirement_spacelift"></a> spacelift>= 1.14

Providers

NameVersion
<a name="provider_spacelift"></a> spacelift1.19.0

Modules

NameSourceVersion
<a name="module_deep"></a> deepcloudposse/config/yaml//modules/deepmerge1.0.2

Resources

NameType
spacelift_aws_integration_attachment.defaultresource
spacelift_drift_detection.defaultresource
spacelift_stack.defaultresource
spacelift_stack_destructor.defaultresource

Inputs

NameDescriptionTypeDefaultRequired
<a name="input_administrative"></a> administrativeFlag to mark the stack as administrativeboolfalseno
<a name="input_after_apply"></a> after_applyList of after-apply scriptslist(string)[]no
<a name="input_after_destroy"></a> after_destroyList of after-destroy scriptslist(string)[]no
<a name="input_after_init"></a> after_initList of after-init scriptslist(string)[]no
<a name="input_after_perform"></a> after_performList of after-perform scriptslist(string)[]no
<a name="input_after_plan"></a> after_planList of after-plan scriptslist(string)[]no
<a name="input_all_root_modules_enabled"></a> all_root_modules_enabledWhen set to true, all subdirectories in root_modules_path will be treated as root modules.boolfalseno
<a name="input_autodeploy"></a> autodeployFlag to enable/disable automatic deployment of the stackbooltrueno
<a name="input_autoretry"></a> autoretryFlag to enable/disable automatic retry of the stackboolfalseno
<a name="input_aws_integration_attachment_read"></a> aws_integration_attachment_readIndicates whether this attachment is used for read operations.booltrueno
<a name="input_aws_integration_attachment_write"></a> aws_integration_attachment_writeIndicates whether this attachment is used for write operations.booltrueno
<a name="input_aws_integration_enabled"></a> aws_integration_enabledIndicates whether the AWS integration is enabled.boolfalseno
<a name="input_aws_integration_id"></a> aws_integration_idID of the AWS integration to attach.stringnullno
<a name="input_before_apply"></a> before_applyList of before-apply scriptslist(string)[]no
<a name="input_before_destroy"></a> before_destroyList of before-destroy scriptslist(string)[]no
<a name="input_before_init"></a> before_initList of before-init scriptslist(string)[]no
<a name="input_before_perform"></a> before_performList of before-perform scriptslist(string)[]no
<a name="input_before_plan"></a> before_planList of before-plan scriptslist(string)[]no
<a name="input_branch"></a> branchSpecify which branch to use within the infrastructure repository.string"main"no
<a name="input_common_config_file"></a> common_config_fileName of the common configuration file for the stack across a root module.string"common.yaml"no
<a name="input_default_tf_workspace_enabled"></a> default_tf_workspace_enabledEnables the use of default Terraform workspace instead of managing multiple workspaces within a root module.<br><br>NOTE: We encourage the use of Terraform workspaces to manage multiple environments.<br>However, you will want to disable this behavior if you're utilizing different backends for each instance<br>of your root modules (we call this "Dynamic Backends").boolfalseno
<a name="input_description"></a> descriptionDescription of the stackstring"Managed by spacelift-automation Terraform root module."no
<a name="input_destructor_enabled"></a> destructor_enabledFlag to enable/disable the destructor for the Stack.boolfalseno
<a name="input_drift_detection_enabled"></a> drift_detection_enabledFlag to enable/disable Drift Detection configuration for a Stack.boolfalseno
<a name="input_drift_detection_ignore_state"></a> drift_detection_ignore_stateControls whether drift detection should be performed on a stack<br>in any final state instead of just 'Finished'.boolfalseno
<a name="input_drift_detection_reconcile"></a> drift_detection_reconcileFlag to enable/disable automatic reconciliation of drifts.boolfalseno
<a name="input_drift_detection_schedule"></a> drift_detection_scheduleThe schedule for drift detection.list(string)<pre>[<br> "0 4 * * *"<br>]</pre>no
<a name="input_drift_detection_timezone"></a> drift_detection_timezoneThe timezone for drift detection.string"UTC"no
<a name="input_enable_local_preview"></a> enable_local_previewIndicates whether local preview runs can be triggered on this Stack.boolfalseno
<a name="input_enable_well_known_secret_masking"></a> enable_well_known_secret_maskingIndicates whether well-known secret masking is enabled.booltrueno
<a name="input_enabled_root_modules"></a> enabled_root_modulesList of root modules where to look for stack config files.<br>Ignored when all_root_modules_enabled is true.<br>Example: ["spacelift-automation", "k8s-cluster"]list(string)[]no
<a name="input_github_action_deploy"></a> github_action_deployIndicates whether GitHub users can deploy from the Checks API.booltrueno
<a name="input_github_enterprise"></a> github_enterpriseThe GitHub VCS settings<pre>object({<br> namespace = string<br> id = optional(string)<br> })</pre>n/ayes
<a name="input_manage_state"></a> manage_stateDetermines if Spacelift should manage state for this stack.boolfalseno
<a name="input_protect_from_deletion"></a> protect_from_deletionProtect this stack from accidental deletion. If set, attempts to delete this stack will fail.boolfalseno
<a name="input_repository"></a> repositoryThe name of your infrastructure repostringn/ayes
<a name="input_root_modules_path"></a> root_modules_pathThe path, relative to the root of the repository, where the root module can be found.string"root-modules"no
<a name="input_space_id"></a> space_idPlace the stack in the specified space_id.string"root"no
<a name="input_terraform_smart_sanitization"></a> terraform_smart_sanitizationIndicates whether runs on this will use terraform's sensitive value system to sanitize<br>the outputs of Terraform state and plans in spacelift instead of sanitizing all fields.boolfalseno
<a name="input_terraform_version"></a> terraform_versionTerraform version to use.string"1.7.2"no
<a name="input_terraform_workflow_tool"></a> terraform_workflow_toolDefines the tool that will be used to execute the workflow.<br>This can be one of OPEN_TOFU, TERRAFORM_FOSS or CUSTOM.string"OPEN_TOFU"no
<a name="input_worker_pool_id"></a> worker_pool_idID of the worker pool to use.<br>NOTE: worker_pool_id is required when using a self-hosted instance of Spacelift.stringnullno

Outputs

NameDescription
<a name="output_spacelift_stacks"></a> spacelift_stacksA map of Spacelift stacks with selected attributes.<br>To reduce the risk of accidentally exporting sensitive data, only a subset of attributes is exported.
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

Contributing

Contributions are welcome and appreciated!

Found an issue or want to request a feature? Open an issue

Want to fix a bug you found or add some functionality? Fork, clone, commit, push, and PR and we'll check it out.

If you have any issues or are waiting a long time for a PR to get merged then feel free to ping us at hello@masterpoint.io.

Built By

Masterpoint Logo