Skip to content

refactor: split cloud providers into separate modules#59

Open
philip-gai wants to merge 9 commits into
lucavallin:mainfrom
philip-gai:philip-gai/modules
Open

refactor: split cloud providers into separate modules#59
philip-gai wants to merge 9 commits into
lucavallin:mainfrom
philip-gai:philip-gai/modules

Conversation

@philip-gai
Copy link
Copy Markdown
Contributor

@philip-gai philip-gai commented Apr 4, 2025

Summary

This PR refactors the Terraform configuration by splitting each cloud provider (AWS, Azure, GCP) into its own module under src/. This improves maintainability, allows for independent versioning, and makes it easier to use only the cloud providers you need.

Changes

Structure

  • Created src/aws/ module for AWS OIDC configuration
  • Created src/azure/ module for Azure OIDC configuration
  • Created src/gcp/ module for GCP OIDC configuration
  • Each module is self-contained with its own main.tf, variables.tf, outputs.tf, provider.tf, and versions.tf

Code Quality

  • AWS: Created aws_client_id_list local to avoid duplicating client IDs
  • Azure: Removed unnecessary local variables, inlined values used only once
  • GCP: Fixed variable description and used lowercase region default

Dependabot

  • Updated .github/dependabot.yml to track provider updates in each module directory

Testing

  • All modules pass terraform fmt -check
  • All modules pass terraform validate

Comment thread .devcontainer/devcontainer.json
Copy link
Copy Markdown
Owner

@lucavallin lucavallin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution! This is a much needed upgrade. I left a few comments. Also, modules normally follow a certain structure (e.g. modules are inside a "modules" directory outside of the main "src" directory). Have a look at https://www.env0.com/blog/terraform-modules

Comment thread src/aws/main.tf Outdated
resource "aws_iam_openid_connect_provider" "this" {
url = local.oidc_issuer_uri
client_id_list = [local.aws_sts_endpoint]
client_id_list = ["sts.amazonaws.com", local.aws_sts_endpoint]
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should sts.amazonaws.com always be in the client list?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sts.amazonaws.com is now always included. I've created a local variable aws_client_id_list that includes both sts.amazonaws.com and the regional STS endpoint, and this is used in both the OIDC provider and the IAM role policy.

Comment thread src/aws/main.tf Outdated
"${aws_iam_openid_connect_provider.this.url}:aud" = local.aws_sts_endpoint
"${aws_iam_openid_connect_provider.this.url}:sub" : "${local.ghes_hostname}",
"${aws_iam_openid_connect_provider.this.url}:aud" = [
"sts.amazonaws.com",
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should create a local var for this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Created aws_client_id_list local variable that's now used in both the client_id_list attribute and the IAM role policy aud condition.

Comment thread src/aws/provider.tf
@@ -1,14 +1,6 @@
provider "azurerm" {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to update the dependabot config to keep it updating the providers?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Updated .github/dependabot.yml to include entries for /src/aws, /src/azure, and /src/gcp directories so providers in each module will be kept up to date.

Comment thread src/azure/main.tf
azure_blob_endpoint_suffix = "core.windows.net"
}

resource "random_string" "long" {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we use this across modules, we could have modules take in a random prefix as a variable, and generate the random prefix in our main.tf

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this is a long random string, presumably by design, it might be worth considering adding validation for its length if you’re accepting it as a variable. Also, I’d recommend reconsidering whether it’s necessary to expose it as a variable—doing so could add unnecessary noise to the module interface. Is there other than the above mentioned reason another reason to make it a variable?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point from both of you. I've opted to keep the random_string resource within each module for now to keep them self-contained and avoid adding complexity to the module interface. This way each module is independently usable without requiring external dependencies. Happy to revisit if there's a strong preference otherwise.

Copy link
Copy Markdown

@bschaatsbergen bschaatsbergen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey 👋🏼, nice job on splitting this out. I left a few drive-by comments. They’re just meant to highlight some things for consideration.

Comment thread src/azure/main.tf Outdated
locals {
ghes_name = var.GHES_NAME
ghes_hostname = var.GHES_HOSTNAME
oidc_issuer_uri = "https://${local.ghes_hostname}/_services/token"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this local referenced elsewhere? I see it used just once here (in the context of this PR), it's advised to avoid reserving a local variable for it in this case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Removed oidc_issuer_uri local and inlined the value directly where it's used since it was only referenced once.

Comment thread src/azure/main.tf Outdated
azure_region = var.AZURE_REGION
azure_storage_account_tier = var.AZURE_STORAGE_ACCOUNT_TIER
azure_storage_account_replication_type = var.AZURE_STORAGE_ACCOUNT_REPLICATION_TYPE
azure_blob_endpoint_suffix = "core.windows.net"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, is this local referenced anywhere other than the existing output block? If not, it might be better to place the string literal ("core.windows.net") directly within the output block.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Removed azure_blob_endpoint_suffix local and now using the literal "core.windows.net" directly in the output block.

Comment thread src/azure/main.tf
azure_blob_endpoint_suffix = "core.windows.net"
}

resource "random_string" "long" {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this is a long random string, presumably by design, it might be worth considering adding validation for its length if you’re accepting it as a variable. Also, I’d recommend reconsidering whether it’s necessary to expose it as a variable—doing so could add unnecessary noise to the module interface. Is there other than the above mentioned reason another reason to make it a variable?

Comment thread src/gcp/variables.tf
@@ -0,0 +1,20 @@
variable "GHES_NAME" {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed the variable names are all caps. Is there a particular reason for this choice? In Terraform, the standard convention is to use camelCase or snake_case for variable names, and aligning with this could improve consistency with other publicly available modules. This might also help reduce cognitive load for users who are familiar with the conventions.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point of thought: since this was likely already released and in use, I would recommend avoiding any breaking changes—unless you haven’t yet reached any end users.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed on avoiding breaking changes. The all-caps variable names are from the original codebase, so I'm keeping them as-is to maintain backward compatibility for existing users.

Comment thread src/gcp/variables.tf Outdated

variable "GCP_PROJECT_ID" {
type = string
description = "Google Cloud: ID of the Project to use"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description = "Google Cloud: ID of the Project to use"
description = "ID of the Google Cloud project to be used."

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied! Updated description to "ID of the Google Cloud project to be used."

Comment thread src/gcp/variables.tf Outdated
variable "GCP_REGION" {
type = string
description = "Google Cloud: Region for OIDC Resources"
default = "EUROPE-WEST4"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the provider accept the region in all caps? It’s possible that the provider or the underlying Google Cloud SDKs are normalizing the capitalization, but I would recommend sticking to lowercase for consistency. Was there a specific reason for using all caps?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Changed the default from EUROPE-WEST4 to europe-west4 for consistency with standard conventions.

- AWS: Create local var aws_client_id_list to avoid duplication
- Azure: Remove unnecessary local vars (oidc_issuer_uri, azure_blob_endpoint_suffix)
- GCP: Fix variable description and use lowercase region default
- Update dependabot config to include module directories
@philip-gai philip-gai changed the title Split out modules for each cloud provider Split cloud providers into separate modules Jan 20, 2026
- Resolve merge conflicts
- Update AWS provider to 6.19.0
- Update Azure provider to 4.51.0, AzureAD to 3.6.0
- Update GCP provider to 7.9.0
- Update random provider to 3.7.2 across all modules
@philip-gai philip-gai changed the title Split cloud providers into separate modules refactor: split cloud providers into separate modules Jan 20, 2026
Copy link
Copy Markdown
Contributor Author

@philip-gai philip-gai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed all feedback - see individual replies on each thread.

@lucavallin
Copy link
Copy Markdown
Owner

Fantastic, great work! I assume everything is working fine? I'd double check myself normally, but it's hectic times here... ;)

@lucavallin
Copy link
Copy Markdown
Owner

@philip-gai Just a ping to know I can merge this ;)

@lucavallin
Copy link
Copy Markdown
Owner

@philip-gai Ping!

@philip-gai
Copy link
Copy Markdown
Contributor Author

Sorry @lucavallin haven't had the chance to get this all setup and re-test it 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants