diff --git a/.github/workflows/terraform-validate.yml b/.github/workflows/terraform-validate.yml new file mode 100644 index 0000000..06accc7 --- /dev/null +++ b/.github/workflows/terraform-validate.yml @@ -0,0 +1,80 @@ +name: Terraform Validate + +on: + pull_request: + branches: + - "**" + paths: + - "terraform/**" + - ".github/workflows/terraform-validate.yml" + +jobs: + discover-modules: + name: Discover Modules + runs-on: ubuntu-latest + outputs: + modules: ${{ steps.find.outputs.modules }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Find Terraform modules + id: find + run: | + modules=$(ls -d terraform/modules/*/ | xargs -I{} basename {} | jq -R -s -c 'split("\n") | map(select(. != ""))') + echo "modules=${modules}" >> "$GITHUB_OUTPUT" + echo "Discovered modules: ${modules}" + + validate: + name: "Validate: ${{ matrix.module }}" + runs-on: ubuntu-latest + needs: discover-modules + strategy: + fail-fast: false + matrix: + module: ${{ fromJson(needs.discover-modules.outputs.modules) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: "~> 1.5" + + - name: Terraform Format Check (module) + run: terraform fmt -check -recursive -diff + working-directory: terraform/modules/${{ matrix.module }} + + - name: Terraform Init (fixture) + run: terraform init + working-directory: terraform/tests/fixtures/${{ matrix.module }} + + - name: Terraform Validate (fixture) + run: terraform validate + working-directory: terraform/tests/fixtures/${{ matrix.module }} + + tflint: + name: "TFLint: ${{ matrix.module }}" + runs-on: ubuntu-latest + needs: discover-modules + strategy: + fail-fast: false + matrix: + module: ${{ fromJson(needs.discover-modules.outputs.modules) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup TFLint + uses: terraform-linters/setup-tflint@v4 + with: + tflint_version: latest + + - name: Init TFLint + run: tflint --init --config "${{ github.workspace }}/terraform/.tflint.hcl" + working-directory: terraform/modules/${{ matrix.module }} + + - name: Run TFLint + run: tflint --config "${{ github.workspace }}/terraform/.tflint.hcl" --format compact + working-directory: terraform/modules/${{ matrix.module }} diff --git a/terraform/.tflint.hcl b/terraform/.tflint.hcl new file mode 100644 index 0000000..46fdc1d --- /dev/null +++ b/terraform/.tflint.hcl @@ -0,0 +1,21 @@ +plugin "terraform" { + enabled = true + preset = "recommended" +} + +# These rules are disabled because the existing modules do not yet declare +# required_providers or required_version in their terraform blocks. +# Enable them once the modules are updated. +rule "terraform_required_providers" { + enabled = false +} + +rule "terraform_required_version" { + enabled = false +} + +plugin "aws" { + enabled = true + version = "0.35.0" + source = "github.com/terraform-linters/tflint-ruleset-aws" +} diff --git a/terraform/modules/namespaces/variables.tf b/terraform/modules/namespaces/variables.tf index dbb9df2..7d887b6 100644 --- a/terraform/modules/namespaces/variables.tf +++ b/terraform/modules/namespaces/variables.tf @@ -1,15 +1,15 @@ variable "namespaces" { description = "List of namespaces to create with their configuration" type = list(object({ - name = string - environment = string - team = string - extra_labels = optional(map(string), {}) + name = string + environment = string + team = string + extra_labels = optional(map(string), {}) resource_quota_enabled = optional(bool, true) - cpu_request_limit = optional(string, "2") - memory_request_limit = optional(string, "4Gi") - cpu_limit = optional(string, "4") - memory_limit = optional(string, "8Gi") - max_pods = optional(string, "20") + cpu_request_limit = optional(string, "2") + memory_request_limit = optional(string, "4Gi") + cpu_limit = optional(string, "4") + memory_limit = optional(string, "8Gi") + max_pods = optional(string, "20") })) } diff --git a/terraform/tests/fixtures/dns/main.tf b/terraform/tests/fixtures/dns/main.tf new file mode 100644 index 0000000..2bda5f1 --- /dev/null +++ b/terraform/tests/fixtures/dns/main.tf @@ -0,0 +1,24 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = "us-east-1" + skip_credentials_validation = true + skip_metadata_api_check = true + skip_requesting_account_id = true + + access_key = "mock-access-key" + secret_key = "mock-secret-key" +} + +module "dns" { + source = "../../../modules/dns" + domain_name = "example.com" + tags = { Environment = "test" } +} diff --git a/terraform/tests/fixtures/ecr/main.tf b/terraform/tests/fixtures/ecr/main.tf new file mode 100644 index 0000000..e99295a --- /dev/null +++ b/terraform/tests/fixtures/ecr/main.tf @@ -0,0 +1,24 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = "us-east-1" + skip_credentials_validation = true + skip_metadata_api_check = true + skip_requesting_account_id = true + + access_key = "mock-access-key" + secret_key = "mock-secret-key" +} + +module "ecr" { + source = "../../../modules/ecr" + repository_names = ["test-repo"] + tags = { Environment = "test" } +} diff --git a/terraform/tests/fixtures/eks-cluster/main.tf b/terraform/tests/fixtures/eks-cluster/main.tf new file mode 100644 index 0000000..4611b51 --- /dev/null +++ b/terraform/tests/fixtures/eks-cluster/main.tf @@ -0,0 +1,28 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = "us-east-1" + skip_credentials_validation = true + skip_metadata_api_check = true + skip_requesting_account_id = true + + access_key = "mock-access-key" + secret_key = "mock-secret-key" +} + +module "eks_cluster" { + source = "../../../modules/eks-cluster" + cluster_name = "test-cluster" + cluster_version = "1.31" + vpc_id = "vpc-12345" + private_subnet_ids = ["subnet-111", "subnet-222"] + environment = "test" + tags = { Environment = "test" } +} diff --git a/terraform/tests/fixtures/namespaces/main.tf b/terraform/tests/fixtures/namespaces/main.tf new file mode 100644 index 0000000..2defa12 --- /dev/null +++ b/terraform/tests/fixtures/namespaces/main.tf @@ -0,0 +1,27 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.0" + } + } +} + +provider "kubernetes" { + host = "https://localhost" + + client_certificate = "" + client_key = "" + cluster_ca_certificate = "" +} + +module "namespaces" { + source = "../../../modules/namespaces" + namespaces = [ + { + name = "test-ns" + environment = "test" + team = "platform" + } + ] +} diff --git a/terraform/tests/fixtures/networking/main.tf b/terraform/tests/fixtures/networking/main.tf new file mode 100644 index 0000000..3187fe7 --- /dev/null +++ b/terraform/tests/fixtures/networking/main.tf @@ -0,0 +1,26 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = "us-east-1" + skip_credentials_validation = true + skip_metadata_api_check = true + skip_requesting_account_id = true + + access_key = "mock-access-key" + secret_key = "mock-secret-key" +} + +module "networking" { + source = "../../../modules/networking" + vpc_name = "test-vpc" + vpc_cidr = "10.0.0.0/16" + availability_zones = ["us-east-1a", "us-east-1b"] + tags = { Environment = "test" } +}