Skip to content

Commit

Permalink
Merge pull request #16 from oleksiimorozenko/main
Browse files Browse the repository at this point in the history
Make VCS repo settings and variable sets configurable by workspace
  • Loading branch information
tbulding authored Feb 19, 2024
2 parents fecfdbe + 9aac174 commit fbac407
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 27 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ Currently there is no way to wait for any workspace variable sets prior to the i
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >=4.0.0, < 6.0.0 |
| <a name="requirement_tfe"></a> [tfe](#requirement\_tfe) | >= 0.44.0 |
| <a name="requirement_tfe"></a> [tfe](#requirement\_tfe) | >= 0.51.1 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_tfe"></a> [tfe](#provider\_tfe) | 0.48.0 |
| <a name="provider_tfe"></a> [tfe](#provider\_tfe) | >= 0.51.1 |

## Modules

Expand All @@ -100,7 +100,9 @@ No modules.
|------|------|
| [tfe_variable.workspace](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/variable) | resource |
| [tfe_workspace.main](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace) | resource |
| [tfe_workspace_settings.this](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace_settings) | resource |
| [tfe_workspace_variable_set.shared_preexisting_variable_set_ids](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace_variable_set) | resource |
| [tfe_workspace_variable_set.this](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace_variable_set) | resource |

## Inputs

Expand All @@ -110,7 +112,7 @@ No modules.
| <a name="input_workspaces"></a> [workspaces](#input\_workspaces) | Nested map of workspaces to create and the associated arguments they can accept:<br><br>Example:<pre>workspaces = {<br> eastcoast = {<br> vars = {<br> AWS_REGION = {<br> value = "us-east-1"<br> }<br> }<br> }<br> westcoast = {...}<br> }</pre>Arguments accepted within workspace definition:<br><br>- All arguments from [tfe\_workspace](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace#argument-reference). Defaults set as documented in July 2022 (v0.33.0).<br>- `vars` = A nested map of variables, their value and category<pre>vars = {<br> myvar_name = {<br> value = "my var value"<br> category = "env" # valid values: "env" or "terraform", default = "env"<br> }<br> }</pre>Workspace `tag_names` will attempt to combine specific tag\_names and from `var.shared_workspace_tag_names`. | `any` | n/a | yes |
| <a name="input_shared_variable_set_ids"></a> [shared\_variable\_set\_ids](#input\_shared\_variable\_set\_ids) | A variable set ID to set to all workspaces. Use if you have a pre-existing variable set. | `list(string)` | `[]` | no |
| <a name="input_shared_workspace_tag_names"></a> [shared\_workspace\_tag\_names](#input\_shared\_workspace\_tag\_names) | Tag names to set for all workspaces. To set per-workspace, see `var.workspaces`. | `list(any)` | `[]` | no |
| <a name="input_vcs_repo"></a> [vcs\_repo](#input\_vcs\_repo) | Definition of the VCS repo to attach to every workspace. | <pre>object({<br> identifier = string<br> oauth_token_id = string<br> branch = optional(string)<br> })</pre> | `null` | no |
| <a name="input_vcs_repo"></a> [vcs\_repo](#input\_vcs\_repo) | Definition of the VCS repo to attach to every workspace. | <pre>object({<br> branch = optional(string)<br> github_app_installation_id = optional(string)<br> identifier = string<br> ingress_submodules = optional(bool)<br> oauth_token_id = optional(string)<br> })</pre> | `null` | no |

## Outputs

Expand Down
4 changes: 2 additions & 2 deletions examples/basic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.2.2 |
| <a name="requirement_tfe"></a> [tfe](#requirement\_tfe) | ~> 0.48 |
| <a name="requirement_tfe"></a> [tfe](#requirement\_tfe) | ~> 0.51 |

## Providers

Expand All @@ -25,7 +25,7 @@ No resources.
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_organization"></a> [organization](#input\_organization) | n/a | `any` | n/a | yes |
| <a name="input_vcs_repo"></a> [vcs\_repo](#input\_vcs\_repo) | Definition of the VCS repo to attach to every workspace. | <pre>object({<br> identifier = string<br> oauth_token_id = string<br> branch = optional(string)<br> })</pre> | `null` | no |
| <a name="input_vcs_repo"></a> [vcs\_repo](#input\_vcs\_repo) | Definition of the VCS repo to attach to every workspace. | <pre>object({<br> branch = optional(string)<br> github_app_installation_id = optional(string)<br> identifier = string<br> ingress_submodules = optional(bool)<br> oauth_token_id = optional(string)<br> })</pre> | `null` | no |

## Outputs

Expand Down
2 changes: 1 addition & 1 deletion examples/basic/providers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ terraform {

required_providers {
tfe = {
version = "~> 0.48"
version = "~> 0.51"
}
}
}
8 changes: 5 additions & 3 deletions examples/basic/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ variable "vcs_repo" {
default = null

type = object({
identifier = string
oauth_token_id = string
branch = optional(string)
branch = optional(string)
github_app_installation_id = optional(string)
identifier = string
ingress_submodules = optional(bool)
oauth_token_id = optional(string)
})
}

Expand Down
5 changes: 5 additions & 0 deletions examples/vcs-options/.header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
This example shows how to change default VCS setting behavior
By default, if `vcs_repo` variable is set, VCS is enabled across all the workspaces
In case if it needs to be customized, there are two options:
- set `vcs_repo_enable` to `false` to not enable VCS at all
- set `vcs_repo` within particular workspace to enable VCS with custom settings (e.g. repository, branch, token etc.)
42 changes: 42 additions & 0 deletions examples/vcs-options/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!-- BEGIN_TF_DOCS -->
This example shows how to change default VCS setting behavior
By default, if `vcs_repo` variable is set, VCS is enabled across all the workspaces
In case if it needs to be customized, there are two options:
- set `vcs_repo_enable` to `false` to not enable VCS at all
- set `vcs_repo` within particular workspace to enable VCS with custom settings (e.g. repository, branch, token etc.)

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.2.2 |
| <a name="requirement_tfe"></a> [tfe](#requirement\_tfe) | ~> 0.51 |

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_multi_region_deployment"></a> [multi\_region\_deployment](#module\_multi\_region\_deployment) | ../.. | n/a |

## Resources

No resources.

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_organization"></a> [organization](#input\_organization) | n/a | `any` | n/a | yes |
| <a name="input_vcs_repo"></a> [vcs\_repo](#input\_vcs\_repo) | Definition of the VCS repo to attach to every workspace. | <pre>object({<br> branch = optional(string)<br> github_app_installation_id = optional(string)<br> identifier = string<br> ingress_submodules = optional(bool)<br> oauth_token_id = optional(string)<br> })</pre> | `null` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_workspace_attrributes"></a> [workspace\_attrributes](#output\_workspace\_attrributes) | n/a |
| <a name="output_workspace_ids"></a> [workspace\_ids](#output\_workspace\_ids) | n/a |
<!-- END_TF_DOCS -->
39 changes: 39 additions & 0 deletions examples/vcs-options/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#####################################################################################
# Terraform module examples are meant to show an _example_ on how to use a module
# per use-case. The code below should not be copied directly but referenced in order
# to build your own root module that invokes this module
#####################################################################################

module "multi_region_deployment" {
source = "../.."

organization = var.organization

vcs_repo = {
identifier = "orgname/repo"
oauth_token_id = "ot-0AuTH_T0kEn_1D"
branch = "some_branch" # Can be omitted, the default branch will be used (https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace#branch)
}

workspaces = {
eastcoast = {
vars = {
AWS_REGION = {
value = "us-east-1"
}
}
}
westcoast = {}
# This workspace will not enable VCS
disabled_vcs = {
vcs_repo_enable = false
}
# This workspace will enable VCS but not inherit VCS general settings
custom_vcs = {
vcs_repo = {
identifier = "orgname/other_repo"
oauth_token_id = "ot-0AuTH_T0kEn_1D"
}
}
}
}
9 changes: 9 additions & 0 deletions examples/vcs-options/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "workspace_ids" {
value = [for ws in module.multi_region_deployment.workspaces_attributes :
ws.id
]
}

output "workspace_attrributes" {
value = module.multi_region_deployment.workspaces_attributes
}
9 changes: 9 additions & 0 deletions examples/vcs-options/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
terraform {
required_version = ">= 1.2.2"

required_providers {
tfe = {
version = "~> 0.51"
}
}
}
23 changes: 23 additions & 0 deletions examples/vcs-options/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# variable "workspace_name" {
# default = {
# value = "test"
# category = "terraform"
# }
# }

variable "vcs_repo" {
description = "Definition of the VCS repo to attach to every workspace."
default = null

type = object({
branch = optional(string)
github_app_installation_id = optional(string)
identifier = string
ingress_submodules = optional(bool)
oauth_token_id = optional(string)
})
}

variable "organization" {}
# variable "creds_variable_set_name" {}
# variable "shared_variable_set" {}
45 changes: 31 additions & 14 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
locals {
individual_workspace_vars_map = { for w, value in var.workspaces : w => value.vars if try(value.vars, {}) != {} }
individual_workspace_vars = flatten([for workspace, variables in local.individual_workspace_vars_map : [for variable in keys(variables) : "${workspace}/${variable}"]])
individual_workspace_vars_map = { for w, value in var.workspaces : w => value.vars if try(value.vars, {}) != {} }
individual_workspace_vars = flatten([for workspace, variables in local.individual_workspace_vars_map : [for variable in keys(variables) : "${workspace}/${variable}"]])
individual_workspace_vcs_repo_arguments_map = { for r, value in var.workspaces : r => value.vcs_repo if try(value.vcs_repo, {}) != {} }
individual_workspace_vsids_map = { for v, value in var.workspaces : v => value.variable_set_ids if try(value.variable_set_ids, {}) != {} }
individual_workspace_vsids = flatten([for workspace, vsids in local.individual_workspace_vsids_map : [for vsid in vsids : "${workspace}/${vsid}"]])
# shared_variable_sets_per_workspace = { for w, value in var.workspaces : w => value.vars if try(value.vars, {}) != {} }
}

Expand All @@ -11,13 +14,10 @@ resource "tfe_workspace" "main" {
organization = var.organization
project_id = try(each.value["project_id"], null)

allow_destroy_plan = try(each.value["allow_destroy_plan"], null)
assessments_enabled = try(each.value["assessments_enabled"], false) # drift detection
auto_apply = try(each.value["auto_apply"], true)
description = try(each.value["description"], null)
# Set to "agent" if agent_pool_id is set
execution_mode = can(each.value["agent_pool_id"] != null) ? "agent" : try(each.value["execution_mode"], "remote")
agent_pool_id = try(each.value["agent_pool_id"], null)
allow_destroy_plan = try(each.value["allow_destroy_plan"], null)
assessments_enabled = try(each.value["assessments_enabled"], false) # drift detection
auto_apply = try(each.value["auto_apply"], true)
description = try(each.value["description"], null)
file_triggers_enabled = try(each.value["file_triggers_enabled"], true)
global_remote_state = try(each.value["global_remote_state"], null)
remote_state_consumer_ids = try(each.value["remote_state_consumer_ids"], null)
Expand All @@ -26,17 +26,19 @@ resource "tfe_workspace" "main" {
structured_run_output_enabled = try(each.value["structured_run_output_enabled"], true)
ssh_key_id = try(each.value["ssh_key_id"], null)
terraform_version = try(each.value["terraform_version"], null)
trigger_patterns = try(each.value["trigger_patterns"], null)
trigger_prefixes = try(each.value["trigger_prefixes"], null)
working_directory = try(each.value["working_directory"], null)
tag_names = concat(var.shared_workspace_tag_names, try(each.value["tag_names"], []))

dynamic "vcs_repo" {
for_each = var.vcs_repo == null ? [] : ["true"]

for_each = ((try(var.vcs_repo, null) != null) && try(each.value.vcs_repo_enable, true)) ? [true] : []
content {
identifier = var.vcs_repo["identifier"]
oauth_token_id = var.vcs_repo["oauth_token_id"]
branch = try(var.vcs_repo["branch"], "main")
branch = (try(each.value.vcs_repo_enable, false) && can(each.value.vcs_repo != null)) ? try(local.individual_workspace_vcs_repo_arguments_map[each.key].branch, null) : try(var.vcs_repo.branch, null)
github_app_installation_id = (try(each.value.vcs_repo_enable, false) && can(each.value.vcs_repo != null)) ? try(local.individual_workspace_vcs_repo_arguments_map[each.key].github_app_installation_id, null) : try(var.vcs_repo.github_app_installation_id, null)
identifier = (try(each.value.vcs_repo_enable, false) && can(each.value.vcs_repo != null)) ? try(local.individual_workspace_vcs_repo_arguments_map[each.key].identifier, null) : var.vcs_repo.identifier
ingress_submodules = (try(each.value.vcs_repo_enable, false) && can(each.value.vcs_repo != null)) ? try(local.individual_workspace_vcs_repo_arguments_map[each.key].ingress_submodules, null) : try(var.vcs_repo.ingress_submodules, null)
oauth_token_id = (try(each.value.vcs_repo_enable, false) && can(each.value.vcs_repo != null)) ? try(local.individual_workspace_vcs_repo_arguments_map[each.key].oauth_token_id, null) : try(var.vcs_repo.oauth_token_id, null)
}
}
}
Expand All @@ -63,6 +65,21 @@ resource "tfe_variable" "workspace" {
description = try(var.workspaces[split("/", each.key)[0]].vars[split("/", each.key)[1]].description, null)
}

resource "tfe_workspace_settings" "this" {
for_each = var.workspaces

workspace_id = tfe_workspace.main[each.key].id
execution_mode = can(each.value["agent_pool_id"] != null) ? "agent" : try(each.value["execution_mode"], "remote")
agent_pool_id = can(each.value["agent_pool_id"] != null) ? each.value["agent_pool_id"] : null
}

resource "tfe_workspace_variable_set" "this" {
for_each = toset(local.individual_workspace_vsids)

workspace_id = tfe_workspace.main[split("/", each.key)[0]].id
variable_set_id = split("/", each.key)[1]
}

# # create variable set for workspaces that specify their own variables
# resource "tfe_variable_set" "per_workspace" {
# count = var.shared_variable_set == {} ? 0 : 1
Expand Down
2 changes: 1 addition & 1 deletion providers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ terraform {
}
tfe = {
source = "hashicorp/tfe"
version = ">= 0.44.0"
version = ">= 0.51.1"
}
}
}
8 changes: 5 additions & 3 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ variable "vcs_repo" {
default = null

type = object({
identifier = string
oauth_token_id = string
branch = optional(string)
branch = optional(string)
github_app_installation_id = optional(string)
identifier = string
ingress_submodules = optional(bool)
oauth_token_id = optional(string)
})
}

Expand Down

0 comments on commit fbac407

Please sign in to comment.