├── .gitignore ├── lesson-2 └── aws │ ├── backend │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ └── eu-north-1 │ ├── ec2 │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ ├── sg │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ └── vpc │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── lesson-3 ├── .github │ └── workflows │ │ ├── lesson-3-ci-cd-backend.yaml │ │ └── lesson-3-ci-cd.yaml ├── .gitignore └── aws │ ├── backend │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ └── networking │ ├── sg │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ └── vpc │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── lesson-4 ├── modules │ ├── sg │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── tf-backend │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ └── vpc │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf ├── terraform │ ├── ec2 │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── sg │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── tf-backend │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ └── vpc │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf └── terragrunt │ ├── ec2 │ └── terragrunt.hcl │ ├── sg │ └── terragrunt.hcl │ ├── terragrunt.hcl │ └── vpc │ └── terragrunt.hcl ├── lesson-5 ├── .github │ └── workflows │ │ └── cicd.yaml ├── README.md ├── dev │ ├── ec2 │ │ └── terragrunt.hcl │ ├── sg │ │ └── terragrunt.hcl │ ├── terragrunt.hcl │ └── vpc │ │ └── terragrunt.hcl └── modules │ ├── sg │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ └── vpc │ ├── main.tf │ ├── outputs.tf │ └── variables.tf └── lesson-6-7-8 ├── Dockerfile ├── terraform-iac-non-prod ├── .gitignore ├── .gitlab-ci.yml ├── .pre-commit-config.yaml ├── README.md └── dev │ └── main │ ├── ecr │ ├── project-bar │ │ ├── myapp-1 │ │ │ └── terragrunt.hcl │ │ └── myapp-2 │ │ │ └── terragrunt.hcl │ └── project-foo │ │ ├── myapp-1 │ │ └── terragrunt.hcl │ │ └── myapp-2 │ │ └── terragrunt.hcl │ ├── eks │ └── terragrunt.hcl │ ├── kms │ └── terragrunt.hcl │ ├── networking │ ├── sg │ │ └── terragrunt.hcl │ └── vpc │ │ └── terragrunt.hcl │ ├── rds │ └── demo │ │ └── terragrunt.hcl │ └── terragrunt.hcl ├── terraform-iac-prod ├── .gitignore ├── .pre-commit-config.yaml ├── README.md └── main │ ├── ecr │ ├── project-bar │ │ ├── myapp-1 │ │ │ └── terragrunt.hcl │ │ └── myapp-2 │ │ │ └── terragrunt.hcl │ └── project-foo │ │ ├── myapp-1 │ │ └── terragrunt.hcl │ │ └── myapp-2 │ │ └── terragrunt.hcl │ ├── eks │ └── terragrunt.hcl │ ├── kms │ └── terragrunt.hcl │ ├── networking │ ├── sg │ │ └── terragrunt.hcl │ └── vpc │ │ └── terragrunt.hcl │ ├── rds │ └── demo │ │ └── terragrunt.hcl │ └── terragrunt.hcl └── terraform-modules ├── .gitignore ├── .pre-commit-config.yaml ├── README.md ├── docs └── README.md ├── examples └── README.md └── modules ├── ecr ├── README.md ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf ├── eks ├── README.md ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf ├── kms ├── README.md ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf ├── networking ├── sg │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf └── vpc │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf └── rds └── demo ├── README.md ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # These are some examples of commonly ignored file patterns. 2 | # You should customize this list as applicable to your project. 3 | # Learn more about .gitignore: 4 | # https://www.atlassian.com/git/tutorials/saving-changes/gitignore 5 | 6 | # Local .terraform directories 7 | **/.terraform/* 8 | 9 | .terraform.lock.hcl 10 | 11 | # .tfstate files 12 | *.tfstate 13 | *.tfstate.* 14 | 15 | # Crash log files 16 | crash.log 17 | 18 | # Ignore CLI configuration files 19 | .terraformrc 20 | terraform.rc 21 | 22 | # Ignore override files as they are usually used to override resources locally and so 23 | # are not checked in 24 | override.tf 25 | override.tf.json 26 | *_override.tf 27 | *_override.tf.json 28 | 29 | # Node artifact files 30 | node_modules/ 31 | dist/ 32 | 33 | # Compiled Java class files 34 | *.class 35 | 36 | # Compiled Python bytecode 37 | *.py[cod] 38 | 39 | # Log files 40 | *.log 41 | 42 | # Package files 43 | *.jar 44 | 45 | # Maven 46 | target/ 47 | dist/ 48 | 49 | # JetBrains IDE 50 | .idea/ 51 | 52 | # Unit test reports 53 | TEST*.xml 54 | 55 | # Generated by MacOS 56 | .DS_Store 57 | 58 | # Generated by Windows 59 | Thumbs.db 60 | 61 | # Applications 62 | *.app 63 | *.exe 64 | *.war 65 | 66 | # Large media files 67 | *.mp4 68 | *.tiff 69 | *.avi 70 | *.flv 71 | *.mov 72 | *.wmv 73 | 74 | # Ignored vscode files 75 | .vscode/ 76 | 77 | # Sentinel runtime directory 78 | .sentinel 79 | 80 | # SSH Keys 81 | *.pem 82 | 83 | # terragrunt cache directories 84 | **/.terragrunt-cache/* 85 | -------------------------------------------------------------------------------- /lesson-2/aws/backend/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "aws-terraform-state-backend" 4 | key = "backend/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "aws-terraform-state-locks" 7 | encrypt = true 8 | } 9 | required_providers { 10 | aws = { 11 | source = "hashicorp/aws" 12 | version = "3.56.0" 13 | } 14 | } 15 | required_version = ">= 1.0.2" 16 | } 17 | 18 | provider "aws" { 19 | region = var.aws_region 20 | default_tags { 21 | tags = { 22 | "TerminationDate" = "Permanent", 23 | "Environment" = "Development", 24 | "Team" = "DevOps", 25 | "DeployedBy" = "Terraform", 26 | "Application" = "Terraform Backend", 27 | "OwnerEmail" = "devops@example.com" 28 | } 29 | } 30 | } 31 | 32 | # Create a dynamodb table for locking the state file 33 | resource "aws_dynamodb_table" "terraform_state_locks" { 34 | name = var.dynamodb_table 35 | billing_mode = "PAY_PER_REQUEST" 36 | hash_key = "LockID" 37 | attribute { 38 | name = "LockID" 39 | type = "S" 40 | } 41 | tags = { 42 | "Name" = var.dynamodb_table 43 | "Description" = "DynamoDB terraform table to lock states" 44 | } 45 | } 46 | 47 | # Create an S3 bucket to store the state file in 48 | resource "aws_s3_bucket" "terraform_state" { 49 | bucket = var.state_bucket 50 | versioning { 51 | enabled = true 52 | } 53 | server_side_encryption_configuration { 54 | rule { 55 | apply_server_side_encryption_by_default { 56 | sse_algorithm = "AES256" 57 | } 58 | } 59 | } 60 | object_lock_configuration { 61 | object_lock_enabled = "Enabled" 62 | } 63 | lifecycle { 64 | prevent_destroy = true 65 | } 66 | tags = { 67 | Name = var.state_bucket 68 | Description = "S3 Remote Terraform State Store" 69 | } 70 | } 71 | 72 | resource "aws_s3_bucket_public_access_block" "s3_access_block" { 73 | bucket = aws_s3_bucket.terraform_state.id 74 | block_public_acls = true 75 | block_public_policy = true 76 | ignore_public_acls = true 77 | restrict_public_buckets = true 78 | } -------------------------------------------------------------------------------- /lesson-2/aws/backend/outputs.tf: -------------------------------------------------------------------------------- 1 | output "s3_bucket_id" { 2 | value = aws_s3_bucket.terraform_state.id 3 | description = "The name of the S3 bucket" 4 | } 5 | 6 | output "dynamodb_table_name" { 7 | value = aws_dynamodb_table.terraform_state_locks.name 8 | description = "The name of the DynamoDB table" 9 | } -------------------------------------------------------------------------------- /lesson-2/aws/backend/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS Region for the S3 and DynamoDB" 3 | default = "eu-north-1" 4 | } 5 | 6 | variable "state_bucket" { 7 | description = "S3 bucket for holding Terraform state files. Must be globally unique." 8 | type = string 9 | default = "aws-terraform-state-backend" 10 | } 11 | 12 | variable "dynamodb_table" { 13 | description = "DynamoDB table for locking Terraform states" 14 | type = string 15 | default = "aws-terraform-state-locks" 16 | } -------------------------------------------------------------------------------- /lesson-2/aws/eu-north-1/ec2/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "aws-terraform-state-backend" 4 | key = "eu-north-1/ec2/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "aws-terraform-state-locks" 7 | encrypt = true 8 | } 9 | required_providers { 10 | aws = { 11 | source = "hashicorp/aws" 12 | version = "3.56.0" 13 | } 14 | } 15 | required_version = ">= 1.0.2" 16 | } 17 | 18 | 19 | provider "aws" { 20 | region = var.aws_region 21 | default_tags { 22 | tags = { 23 | "TerminationDate" = "Permanent", 24 | "Environment" = "Development", 25 | "Team" = "DevOps", 26 | "DeployedBy" = "Terraform", 27 | "Description" = "For General Purposes" 28 | "OwnerEmail" = "devops@example.com" 29 | "Type" = "Compute Cloud" 30 | } 31 | } 32 | } 33 | 34 | data "terraform_remote_state" "vpc" { 35 | backend = "s3" 36 | config = { 37 | bucket = "aws-terraform-state-backend" 38 | key = "eu-north-1/vpc/terraform.tfstate" 39 | region = "eu-north-1" 40 | } 41 | } 42 | 43 | data "terraform_remote_state" "sg" { 44 | backend = "s3" 45 | config = { 46 | bucket = "aws-terraform-state-backend" 47 | key = "eu-north-1/sg/terraform.tfstate" 48 | region = "eu-north-1" 49 | } 50 | } 51 | 52 | module "ec2_instance" { 53 | source = "terraform-aws-modules/ec2-instance/aws" 54 | version = "3.1.0" 55 | name = "bastion-host" 56 | instance_type = "t3.micro" 57 | ami = "ami-0f0b4cb72cf3eadf3" 58 | vpc_security_group_ids = [data.terraform_remote_state.sg.outputs.sg_id] 59 | subnet_id = data.terraform_remote_state.vpc.outputs.private_subnets[0] 60 | tags = { 61 | Name = "Bastion-host" 62 | } 63 | } -------------------------------------------------------------------------------- /lesson-2/aws/eu-north-1/ec2/outputs.tf: -------------------------------------------------------------------------------- 1 | output "id" { 2 | description = "The ID of the instance" 3 | value = module.ec2_instance.id 4 | } -------------------------------------------------------------------------------- /lesson-2/aws/eu-north-1/ec2/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS Region" 3 | default = "eu-north-1" 4 | } -------------------------------------------------------------------------------- /lesson-2/aws/eu-north-1/sg/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "aws-terraform-state-backend" 4 | key = "eu-north-1/sg/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "aws-terraform-state-locks" 7 | encrypt = true 8 | } 9 | required_providers { 10 | aws = { 11 | source = "hashicorp/aws" 12 | version = "3.56.0" 13 | } 14 | } 15 | required_version = ">= 1.0.2" 16 | } 17 | 18 | 19 | provider "aws" { 20 | region = var.aws_region 21 | default_tags { 22 | tags = { 23 | "TerminationDate" = "Permanent", 24 | "Environment" = "Development", 25 | "Team" = "DevOps", 26 | "DeployedBy" = "Terraform", 27 | "Description" = "For General Purposes" 28 | "OwnerEmail" = "devops@example.com" 29 | } 30 | } 31 | } 32 | 33 | data "terraform_remote_state" "vpc" { 34 | backend = "s3" 35 | config = { 36 | bucket = "aws-terraform-state-backend" 37 | key = "eu-north-1/vpc/terraform.tfstate" 38 | region = "eu-north-1" 39 | } 40 | } 41 | 42 | resource "aws_security_group" "sg" { 43 | name = "bastion-host-sg" 44 | vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id 45 | ingress { 46 | description = "SSH" 47 | from_port = 22 48 | to_port = 22 49 | protocol = "tcp" 50 | cidr_blocks = ["0.0.0.0/0"] 51 | } 52 | egress { 53 | from_port = 0 54 | to_port = 0 55 | protocol = "-1" 56 | cidr_blocks = ["0.0.0.0/0"] 57 | } 58 | tags = { 59 | Name = "Bastion-host-SG-SSH" 60 | } 61 | } -------------------------------------------------------------------------------- /lesson-2/aws/eu-north-1/sg/outputs.tf: -------------------------------------------------------------------------------- 1 | output "sg_id" { 2 | description = "SG ID" 3 | value = aws_security_group.sg.id 4 | } 5 | -------------------------------------------------------------------------------- /lesson-2/aws/eu-north-1/sg/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS Region" 3 | default = "eu-north-1" 4 | } -------------------------------------------------------------------------------- /lesson-2/aws/eu-north-1/vpc/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "aws-terraform-state-backend" 4 | key = "eu-north-1/vpc/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "aws-terraform-state-locks" 7 | encrypt = true 8 | } 9 | required_providers { 10 | aws = { 11 | source = "hashicorp/aws" 12 | version = "3.56.0" 13 | } 14 | } 15 | required_version = ">= 1.0.2" 16 | } 17 | 18 | 19 | provider "aws" { 20 | region = var.aws_region 21 | default_tags { 22 | tags = { 23 | "TerminationDate" = "Permanent", 24 | "Environment" = "Development", 25 | "Team" = "DevOps", 26 | "DeployedBy" = "Terraform", 27 | "Description" = "For General Purposes" 28 | "OwnerEmail" = "devops@example.com" 29 | "Type" = "Networking" 30 | } 31 | } 32 | } 33 | 34 | data "aws_availability_zones" "available" {} 35 | 36 | module "vpc" { 37 | source = "terraform-aws-modules/vpc/aws" 38 | version = "3.7.0" 39 | name = "Dev-VPC" 40 | cidr = "10.10.0.0/16" 41 | azs = data.aws_availability_zones.available.names 42 | private_subnets = ["10.10.1.0/24", "10.10.2.0/24", "10.10.3.0/24"] 43 | public_subnets = ["10.10.21.0/24", "10.10.22.0/24", "10.10.23.0/24"] 44 | enable_nat_gateway = true 45 | single_nat_gateway = true 46 | one_nat_gateway_per_az = false 47 | } 48 | -------------------------------------------------------------------------------- /lesson-2/aws/eu-north-1/vpc/outputs.tf: -------------------------------------------------------------------------------- 1 | # VPC 2 | output "vpc_id" { 3 | description = "The ID of the VPC" 4 | value = module.vpc.vpc_id 5 | } 6 | 7 | # CIDR blocks 8 | output "vpc_cidr_block" { 9 | description = "The CIDR block of the VPC" 10 | value = module.vpc.vpc_cidr_block 11 | } 12 | 13 | # Subnets 14 | output "private_subnets" { 15 | description = "List of IDs of private subnets" 16 | value = module.vpc.private_subnets 17 | } 18 | 19 | output "public_subnets" { 20 | description = "List of IDs of public subnets" 21 | value = module.vpc.public_subnets 22 | } -------------------------------------------------------------------------------- /lesson-2/aws/eu-north-1/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS Region" 3 | default = "eu-north-1" 4 | } -------------------------------------------------------------------------------- /lesson-3/.github/workflows/lesson-3-ci-cd-backend.yaml: -------------------------------------------------------------------------------- 1 | name: "Terraform CI/CD Backend" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - 'aws/backend/**' 9 | pull_request: 10 | branches: 11 | - main 12 | paths: 13 | - 'aws/backend/**' 14 | 15 | jobs: 16 | terraform: 17 | name: "Terraform" 18 | runs-on: ubuntu-latest 19 | env: 20 | working-directory: aws/backend 21 | defaults: 22 | run: 23 | working-directory: ${{ env.working-directory }} 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@v2 27 | 28 | - name: Configure AWS credentials 29 | uses: aws-actions/configure-aws-credentials@v1 30 | with: 31 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 32 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 33 | aws-region: ${{ secrets.AWS_REGION }} 34 | 35 | - name: Setup Terraform 36 | uses: hashicorp/setup-terraform@v1 37 | with: 38 | terraform_version: 1.0.8 39 | 40 | - name: Terraform Format 41 | id: fmt 42 | run: terraform fmt -check 43 | continue-on-error: true 44 | 45 | - name: Terraform Init 46 | id: init 47 | run: terraform init 48 | 49 | - name: Terraform Validate 50 | id: validate 51 | run: terraform validate -no-color 52 | 53 | - name: Terraform Plan 54 | id: plan 55 | if: github.event_name == 'pull_request' 56 | run: terraform plan -no-color 57 | continue-on-error: true 58 | 59 | - uses: actions/github-script@0.9.0 60 | if: github.event_name == 'pull_request' 61 | env: 62 | PLAN: "terraform\n${{ steps.plan.outputs.stdout }}" 63 | with: 64 | github-token: ${{ secrets.GITHUB_TOKEN }} 65 | script: | 66 | const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\` 67 | #### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\` 68 | #### Terraform Validation 🤖\`${{ steps.validate.outcome }}\` 69 | #### Terraform Plan 📖\`${{ steps.plan.outcome }}\` 70 | 71 |
Show Plan 72 | 73 | \`\`\`${process.env.PLAN}\`\`\` 74 | 75 |
76 | 77 | Results for commit: ${{ github.event.pull_request.head.sha }} 78 | 79 | *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.working-directory }}\`, Workflow: \`${{ github.workflow }}\`*`; 80 | 81 | github.issues.createComment({ 82 | issue_number: context.issue.number, 83 | owner: context.repo.owner, 84 | repo: context.repo.repo, 85 | body: output 86 | }) 87 | 88 | - name: Terraform Plan Status 89 | if: steps.plan.outcome == 'failure' 90 | run: exit 1 91 | 92 | - name: Terraform Apply 93 | if: github.ref == 'refs/heads/main' && github.event_name == 'push' 94 | run: terraform apply -auto-approve -------------------------------------------------------------------------------- /lesson-3/.github/workflows/lesson-3-ci-cd.yaml: -------------------------------------------------------------------------------- 1 | name: "Terraform CI/CD" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - 'aws/networking/vpc/**' 9 | - 'aws/networking/sg/**' 10 | pull_request: 11 | branches: 12 | - main 13 | paths: 14 | - 'aws/networking/vpc/**' 15 | - 'aws/networking/sg/**' 16 | 17 | jobs: 18 | terraform: 19 | strategy: 20 | max-parallel: 1 21 | matrix: 22 | tf_actions_working_dir: [aws/networking/vpc, aws/networking/sg] 23 | name: "Terraform" 24 | runs-on: ubuntu-latest 25 | defaults: 26 | run: 27 | working-directory: ${{ matrix.tf_actions_working_dir }} 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v2 31 | 32 | - name: Configure AWS credentials 33 | uses: aws-actions/configure-aws-credentials@v1 34 | with: 35 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 36 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 37 | aws-region: ${{ secrets.AWS_REGION }} 38 | 39 | - name: Setup Terraform 40 | uses: hashicorp/setup-terraform@v1 41 | with: 42 | terraform_version: 1.0.8 43 | 44 | - name: Terraform Format 45 | id: fmt 46 | run: terraform fmt -check 47 | continue-on-error: true 48 | 49 | - name: Terraform Init 50 | id: init 51 | run: terraform init 52 | 53 | - name: Terraform Validate 54 | id: validate 55 | run: terraform validate -no-color 56 | 57 | - name: Terraform Plan 58 | id: plan 59 | if: github.event_name == 'pull_request' 60 | run: terraform plan -no-color 61 | continue-on-error: true 62 | 63 | - uses: actions/github-script@0.9.0 64 | if: github.event_name == 'pull_request' 65 | env: 66 | PLAN: "terraform\n${{ steps.plan.outputs.stdout }}" 67 | with: 68 | github-token: ${{ secrets.GITHUB_TOKEN }} 69 | script: | 70 | const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\` 71 | #### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\` 72 | #### Terraform Validation 🤖\`${{ steps.validate.outcome }}\` 73 | #### Terraform Plan 📖\`${{ steps.plan.outcome }}\` 74 | 75 |
Show Plan 76 | 77 | \`\`\`${process.env.PLAN}\`\`\` 78 | 79 |
80 | 81 | Results for commit: ${{ github.event.pull_request.head.sha }} 82 | 83 | *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ matrix.tf_actions_working_dir }}\`, Workflow: \`${{ github.workflow }}\`*`; 84 | 85 | github.issues.createComment({ 86 | issue_number: context.issue.number, 87 | owner: context.repo.owner, 88 | repo: context.repo.repo, 89 | body: output 90 | }) 91 | 92 | - name: Terraform Plan Status 93 | if: steps.plan.outcome == 'failure' 94 | run: exit 1 95 | 96 | - name: Terraform Apply 97 | if: github.ref == 'refs/heads/main' && github.event_name == 'push' 98 | run: terraform apply -auto-approve -------------------------------------------------------------------------------- /lesson-3/.gitignore: -------------------------------------------------------------------------------- 1 | # These are some examples of commonly ignored file patterns. 2 | # You should customize this list as applicable to your project. 3 | # Learn more about .gitignore: 4 | # https://www.atlassian.com/git/tutorials/saving-changes/gitignore 5 | 6 | # Local .terraform directories 7 | **/.terraform/* 8 | 9 | .terraform.lock.hcl 10 | 11 | # .tfstate files 12 | *.tfstate 13 | *.tfstate.* 14 | 15 | # Crash log files 16 | crash.log 17 | 18 | # Ignore CLI configuration files 19 | .terraformrc 20 | terraform.rc 21 | 22 | # Ignore override files as they are usually used to override resources locally and so 23 | # are not checked in 24 | override.tf 25 | override.tf.json 26 | *_override.tf 27 | *_override.tf.json 28 | 29 | # Node artifact files 30 | node_modules/ 31 | dist/ 32 | 33 | # Compiled Java class files 34 | *.class 35 | 36 | # Compiled Python bytecode 37 | *.py[cod] 38 | 39 | # Log files 40 | *.log 41 | 42 | # Package files 43 | *.jar 44 | 45 | # Maven 46 | target/ 47 | dist/ 48 | 49 | # JetBrains IDE 50 | .idea/ 51 | 52 | # Unit test reports 53 | TEST*.xml 54 | 55 | # Generated by MacOS 56 | .DS_Store 57 | 58 | # Generated by Windows 59 | Thumbs.db 60 | 61 | # Applications 62 | *.app 63 | *.exe 64 | *.war 65 | 66 | # Large media files 67 | *.mp4 68 | *.tiff 69 | *.avi 70 | *.flv 71 | *.mov 72 | *.wmv 73 | 74 | # Ignored vscode files 75 | .vscode/ 76 | 77 | # Sentinel runtime directory 78 | .sentinel 79 | 80 | # SSH Keys 81 | *.pem -------------------------------------------------------------------------------- /lesson-3/aws/backend/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "aws-terraform-states-backend" 4 | key = "backend/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "aws-terraform-states-lock" 7 | encrypt = true 8 | } 9 | required_providers { 10 | aws = { 11 | source = "hashicorp/aws" 12 | version = "3.56.0" 13 | } 14 | } 15 | required_version = ">= 1.0.2" 16 | } 17 | 18 | provider "aws" { 19 | region = var.aws_region 20 | default_tags { 21 | tags = { 22 | "TerminationDate" = "Permanent", 23 | "Environment" = "Development", 24 | "Team" = "DevOps", 25 | "DeployedBy" = "Terraform", 26 | "Application" = "Terraform Backend", 27 | "OwnerEmail" = "devops@example.com" 28 | } 29 | } 30 | } 31 | 32 | # Create a dynamodb table for locking the state file 33 | resource "aws_dynamodb_table" "terraform_state_locks" { 34 | name = var.dynamodb_table 35 | billing_mode = "PAY_PER_REQUEST" 36 | hash_key = "LockID" 37 | attribute { 38 | name = "LockID" 39 | type = "S" 40 | } 41 | tags = { 42 | "Name" = var.dynamodb_table 43 | "Description" = "DynamoDB terraform table to lock states" 44 | } 45 | } 46 | 47 | # Create an S3 bucket to store the state file in 48 | resource "aws_s3_bucket" "terraform_state" { 49 | bucket = var.state_bucket 50 | versioning { 51 | enabled = true 52 | } 53 | server_side_encryption_configuration { 54 | rule { 55 | apply_server_side_encryption_by_default { 56 | sse_algorithm = "AES256" 57 | } 58 | } 59 | } 60 | object_lock_configuration { 61 | object_lock_enabled = "Enabled" 62 | } 63 | lifecycle { 64 | prevent_destroy = true 65 | } 66 | tags = { 67 | Name = var.state_bucket 68 | Description = "S3 Remote Terraform State Store" 69 | } 70 | } 71 | 72 | resource "aws_s3_bucket_public_access_block" "s3_access_block" { 73 | bucket = aws_s3_bucket.terraform_state.id 74 | block_public_acls = true 75 | block_public_policy = true 76 | ignore_public_acls = true 77 | restrict_public_buckets = true 78 | } -------------------------------------------------------------------------------- /lesson-3/aws/backend/outputs.tf: -------------------------------------------------------------------------------- 1 | output "s3_bucket_id" { 2 | value = aws_s3_bucket.terraform_state.id 3 | description = "The name of the S3 bucket" 4 | } 5 | 6 | output "dynamodb_table_name" { 7 | value = aws_dynamodb_table.terraform_state_locks.name 8 | description = "The name of the DynamoDB table" 9 | } -------------------------------------------------------------------------------- /lesson-3/aws/backend/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS Region for the S3 and DynamoDB" 3 | default = "eu-north-1" 4 | } 5 | 6 | variable "state_bucket" { 7 | description = "S3 bucket for holding Terraform state files. Must be globally unique." 8 | type = string 9 | default = "aws-terraform-states-backend" 10 | } 11 | 12 | variable "dynamodb_table" { 13 | description = "DynamoDB table for locking Terraform states" 14 | type = string 15 | default = "aws-terraform-states-lock" 16 | } -------------------------------------------------------------------------------- /lesson-3/aws/networking/sg/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "aws-terraform-states-backend" 4 | key = "networking/sg/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "aws-terraform-states-lock" 7 | encrypt = true 8 | } 9 | required_providers { 10 | aws = { 11 | source = "hashicorp/aws" 12 | version = "3.56.0" 13 | } 14 | } 15 | required_version = ">= 1.0.2" 16 | } 17 | 18 | 19 | provider "aws" { 20 | region = var.aws_region 21 | default_tags { 22 | tags = { 23 | "TerminationDate" = "Permanent", 24 | "Environment" = "Development", 25 | "Team" = "DevOps", 26 | "DeployedBy" = "Terraform", 27 | "Description" = "For General Purposes" 28 | "OwnerEmail" = "devops@test.com" 29 | } 30 | } 31 | } 32 | 33 | data "terraform_remote_state" "vpc" { 34 | backend = "s3" 35 | config = { 36 | bucket = "aws-terraform-states-backend" 37 | key = "networking/vpc/terraform.tfstate" 38 | region = "eu-north-1" 39 | } 40 | } 41 | 42 | resource "aws_security_group" "sg" { 43 | name = "bastion-host-sg" 44 | vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id 45 | ingress { 46 | description = "SSH" 47 | from_port = 22 48 | to_port = 22 49 | protocol = "tcp" 50 | cidr_blocks = ["0.0.0.0/0"] 51 | } 52 | egress { 53 | from_port = 0 54 | to_port = 0 55 | protocol = "-1" 56 | cidr_blocks = ["0.0.0.0/0"] 57 | } 58 | tags = { 59 | Name = "Bastion-host-SG-SSH" 60 | } 61 | } -------------------------------------------------------------------------------- /lesson-3/aws/networking/sg/outputs.tf: -------------------------------------------------------------------------------- 1 | output "sg_id" { 2 | description = "SG ID" 3 | value = aws_security_group.sg.id 4 | } 5 | -------------------------------------------------------------------------------- /lesson-3/aws/networking/sg/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS Region" 3 | default = "eu-north-1" 4 | } -------------------------------------------------------------------------------- /lesson-3/aws/networking/vpc/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "aws-terraform-states-backend" 4 | key = "networking/vpc/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "aws-terraform-states-lock" 7 | encrypt = true 8 | } 9 | required_providers { 10 | aws = { 11 | source = "hashicorp/aws" 12 | version = "3.56.0" 13 | } 14 | } 15 | required_version = ">= 1.0.2" 16 | } 17 | 18 | 19 | provider "aws" { 20 | region = var.aws_region 21 | default_tags { 22 | tags = { 23 | "TerminationDate" = "Permanent", 24 | "Environment" = "Development", 25 | "Team" = "DevOps", 26 | "DeployedBy" = "Terraform", 27 | "Description" = "For General Purposes" 28 | "OwnerEmail" = "devops@example.com" 29 | "Type" = "Networking" 30 | } 31 | } 32 | } 33 | 34 | data "aws_availability_zones" "available" {} 35 | 36 | module "vpc" { 37 | source = "terraform-aws-modules/vpc/aws" 38 | version = "3.7.0" 39 | name = "Dev-VPC" 40 | cidr = "10.10.0.0/16" 41 | azs = data.aws_availability_zones.available.names 42 | private_subnets = ["10.10.1.0/24", "10.10.2.0/24", "10.10.3.0/24"] 43 | } 44 | -------------------------------------------------------------------------------- /lesson-3/aws/networking/vpc/outputs.tf: -------------------------------------------------------------------------------- 1 | # VPC 2 | output "vpc_id" { 3 | description = "The ID of the VPC" 4 | value = module.vpc.vpc_id 5 | } 6 | 7 | # CIDR blocks 8 | output "vpc_cidr_block" { 9 | description = "The CIDR block of the VPC" 10 | value = module.vpc.vpc_cidr_block 11 | } 12 | 13 | # Subnets 14 | output "private_subnets" { 15 | description = "List of IDs of private subnets" 16 | value = module.vpc.private_subnets 17 | } 18 | 19 | output "public_subnets" { 20 | description = "List of IDs of public subnets" 21 | value = module.vpc.public_subnets 22 | } -------------------------------------------------------------------------------- /lesson-3/aws/networking/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS Region" 3 | default = "eu-north-1" 4 | } -------------------------------------------------------------------------------- /lesson-4/modules/sg/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.1" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.7" 8 | } 9 | } 10 | } 11 | 12 | resource "aws_security_group" "sg" { 13 | name = "${var.deployment_prefix}-bastion-host-sg" 14 | vpc_id = var.vpc_id 15 | ingress { 16 | description = "SSH" 17 | from_port = 22 18 | to_port = 22 19 | protocol = "tcp" 20 | cidr_blocks = var.allowed_cidr_blocks 21 | } 22 | egress { 23 | from_port = 0 24 | to_port = 0 25 | protocol = "-1" 26 | cidr_blocks = ["0.0.0.0/0"] 27 | } 28 | tags = { 29 | Name = "${var.deployment_prefix}-bastion-host-sg" 30 | } 31 | } -------------------------------------------------------------------------------- /lesson-4/modules/sg/outputs.tf: -------------------------------------------------------------------------------- 1 | output "sg_id" { 2 | description = "SG ID" 3 | value = aws_security_group.sg.id 4 | } 5 | -------------------------------------------------------------------------------- /lesson-4/modules/sg/variables.tf: -------------------------------------------------------------------------------- 1 | variable "deployment_prefix" { 2 | description = "Prefix of the deployment." 3 | type = string 4 | } 5 | 6 | variable "vpc_id" { 7 | description = "AWS VPC ID." 8 | type = string 9 | } 10 | 11 | variable "allowed_cidr_blocks" { 12 | description = "List of allowed CIDR blocks for SSH." 13 | type = list(string) 14 | } -------------------------------------------------------------------------------- /lesson-4/modules/tf-backend/README.md: -------------------------------------------------------------------------------- 1 | # Setting up terraform basics 2 | 3 | Shared state file. 4 | S3 config. 5 | DynamoDB 6 | 7 | ## Setup 8 | 9 | ``` 10 | terraform init 11 | 12 | terraform plan 13 | 14 | terraform apply 15 | ``` -------------------------------------------------------------------------------- /lesson-4/modules/tf-backend/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.1" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.7" 8 | } 9 | } 10 | } 11 | 12 | # Create a dynamodb table for locking the state files 13 | resource "aws_dynamodb_table" "terraform_state_locks" { 14 | name = var.dynamodb_table_name 15 | billing_mode = "PAY_PER_REQUEST" 16 | hash_key = "LockID" 17 | attribute { 18 | name = "LockID" 19 | type = "S" 20 | } 21 | server_side_encryption { 22 | enabled = true 23 | } 24 | tags = { 25 | "Name" = var.dynamodb_table_name 26 | "Description" = "DynamoDB terraform table to lock states" 27 | } 28 | } 29 | 30 | # Create an S3 bucket to store the state file in 31 | resource "aws_s3_bucket" "terraform_state" { 32 | bucket = var.s3_bucket_name 33 | tags = { 34 | "Name" = var.s3_bucket_name 35 | "Description" = "S3 Remote Terraform State Store" 36 | } 37 | } 38 | 39 | resource "aws_s3_bucket_versioning" "terraform_state" { 40 | bucket = aws_s3_bucket.terraform_state.id 41 | 42 | versioning_configuration { 43 | status = "Enabled" 44 | } 45 | } 46 | 47 | resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" { 48 | bucket = aws_s3_bucket.terraform_state.id 49 | rule { 50 | apply_server_side_encryption_by_default { 51 | sse_algorithm = "AES256" 52 | } 53 | } 54 | } 55 | 56 | resource "aws_s3_bucket_acl" "terraform_state" { 57 | bucket = aws_s3_bucket.terraform_state.id 58 | acl = "private" 59 | } 60 | 61 | resource "aws_s3_bucket_public_access_block" "s3_access_block" { 62 | bucket = aws_s3_bucket.terraform_state.id 63 | block_public_acls = true 64 | block_public_policy = true 65 | ignore_public_acls = true 66 | restrict_public_buckets = true 67 | } -------------------------------------------------------------------------------- /lesson-4/modules/tf-backend/outputs.tf: -------------------------------------------------------------------------------- 1 | output "s3_bucket_id" { 2 | value = aws_s3_bucket.terraform_state.id 3 | description = "The name of the S3 bucket" 4 | } 5 | 6 | output "dynamodb_table_name" { 7 | value = aws_dynamodb_table.terraform_state_locks.name 8 | description = "The name of the DynamoDB table" 9 | } -------------------------------------------------------------------------------- /lesson-4/modules/tf-backend/variables.tf: -------------------------------------------------------------------------------- 1 | variable "s3_bucket_name" { 2 | description = "S3 bucket for holding Terraform state. Must be globally unique." 3 | type = string 4 | } 5 | 6 | variable "dynamodb_table_name" { 7 | description = "DynamoDB table for locking Terraform states" 8 | type = string 9 | } -------------------------------------------------------------------------------- /lesson-4/modules/vpc/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.1" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.7" 8 | } 9 | } 10 | } 11 | 12 | data "aws_availability_zones" "available" {} 13 | 14 | locals { 15 | cidr_part = trimsuffix(var.cidr, ".0.0") 16 | } 17 | 18 | module "vpc" { 19 | source = "terraform-aws-modules/vpc/aws" 20 | version = "3.14.0" 21 | name = "${var.deployment_prefix}-VPC" 22 | cidr = "${var.cidr}/16" 23 | azs = data.aws_availability_zones.available.names 24 | private_subnets = ["${local.cidr_part}.1.0/24", "${local.cidr_part}.2.0/24", "${local.cidr_part}.3.0/24"] 25 | public_subnets = ["${local.cidr_part}.21.0/24", "${local.cidr_part}.22.0/24", "${local.cidr_part}.23.0/24"] 26 | enable_nat_gateway = false 27 | single_nat_gateway = true 28 | one_nat_gateway_per_az = false 29 | } 30 | -------------------------------------------------------------------------------- /lesson-4/modules/vpc/outputs.tf: -------------------------------------------------------------------------------- 1 | # VPC 2 | output "vpc_id" { 3 | description = "The ID of the VPC" 4 | value = module.vpc.vpc_id 5 | } 6 | 7 | # CIDR blocks 8 | output "vpc_cidr_block" { 9 | description = "The CIDR block of the VPC" 10 | value = module.vpc.vpc_cidr_block 11 | } 12 | 13 | # Subnets 14 | output "private_subnets" { 15 | description = "List of IDs of private subnets" 16 | value = module.vpc.private_subnets 17 | } 18 | 19 | output "public_subnets" { 20 | description = "List of IDs of public subnets" 21 | value = module.vpc.public_subnets 22 | } -------------------------------------------------------------------------------- /lesson-4/modules/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "deployment_prefix" { 2 | description = "Prefix of the deployment." 3 | type = string 4 | } 5 | 6 | variable "cidr" { 7 | description = "The CIDR block for the VPC." 8 | type = string 9 | } -------------------------------------------------------------------------------- /lesson-4/terraform/ec2/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/ec2/README.md -------------------------------------------------------------------------------- /lesson-4/terraform/ec2/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "demo-terraform-states-backend" 4 | key = "ec2/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "demo-terraform-states-backend" 7 | encrypt = true 8 | } 9 | } 10 | 11 | locals { 12 | deployment_prefix = "demo-terraform" 13 | } 14 | 15 | provider "aws" { 16 | region = "eu-north-1" 17 | default_tags { 18 | tags = { 19 | "TerminationDate" = "Permanent", 20 | "Environment" = "Development", 21 | "Team" = "DevOps", 22 | "DeployedBy" = "Terraform", 23 | "OwnerEmail" = "devops@example.com" 24 | "DeploymentPrefix" = local.deployment_prefix 25 | } 26 | } 27 | } 28 | 29 | data "terraform_remote_state" "vpc" { 30 | backend = "s3" 31 | config = { 32 | bucket = "demo-terraform-states-backend" 33 | key = "vpc/terraform.tfstate" 34 | region = "eu-north-1" 35 | } 36 | } 37 | 38 | data "terraform_remote_state" "sg" { 39 | backend = "s3" 40 | config = { 41 | bucket = "demo-terraform-states-backend" 42 | key = "sg/terraform.tfstate" 43 | region = "eu-north-1" 44 | } 45 | } 46 | 47 | module "ec2" { 48 | source = "terraform-aws-modules/ec2-instance/aws" 49 | version = "4.0.0" 50 | name = "${local.deployment_prefix}-bastion-host" 51 | instance_type = "t3.micro" 52 | ami = "ami-08bdc08970fcbd34a" 53 | vpc_security_group_ids = [data.terraform_remote_state.sg.outputs.sg_id] 54 | subnet_id = data.terraform_remote_state.vpc.outputs.public_subnets[0] 55 | tags = { 56 | Name = "${local.deployment_prefix}-bastion-host" 57 | } 58 | } -------------------------------------------------------------------------------- /lesson-4/terraform/ec2/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/ec2/outputs.tf -------------------------------------------------------------------------------- /lesson-4/terraform/ec2/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/ec2/variables.tf -------------------------------------------------------------------------------- /lesson-4/terraform/sg/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/sg/README.md -------------------------------------------------------------------------------- /lesson-4/terraform/sg/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "demo-terraform-states-backend" 4 | key = "sg/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "demo-terraform-states-backend" 7 | encrypt = true 8 | } 9 | } 10 | 11 | locals { 12 | deployment_prefix = "demo-terraform" 13 | } 14 | 15 | provider "aws" { 16 | region = "eu-north-1" 17 | default_tags { 18 | tags = { 19 | "TerminationDate" = "Permanent", 20 | "Environment" = "Development", 21 | "Team" = "DevOps", 22 | "DeployedBy" = "Terraform", 23 | "OwnerEmail" = "devops@example.com" 24 | "DeploymentPrefix" = local.deployment_prefix 25 | } 26 | } 27 | } 28 | 29 | data "terraform_remote_state" "vpc" { 30 | backend = "s3" 31 | config = { 32 | bucket = "demo-terraform-states-backend" 33 | key = "vpc/terraform.tfstate" 34 | region = "eu-north-1" 35 | } 36 | } 37 | 38 | module "sg" { 39 | source = "../../modules/sg/" 40 | vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id 41 | allowed_cidr_blocks = ["10.10.0.0/16", "192.168.0.0/16"] 42 | deployment_prefix = local.deployment_prefix 43 | } -------------------------------------------------------------------------------- /lesson-4/terraform/sg/outputs.tf: -------------------------------------------------------------------------------- 1 | output "sg_id" { 2 | description = "SG ID" 3 | value = module.sg.sg_id 4 | } 5 | -------------------------------------------------------------------------------- /lesson-4/terraform/sg/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/sg/variables.tf -------------------------------------------------------------------------------- /lesson-4/terraform/tf-backend/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/tf-backend/README.md -------------------------------------------------------------------------------- /lesson-4/terraform/tf-backend/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "demo-terraform-states-backend" 4 | key = "tf-backend/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "demo-terraform-states-backend" 7 | encrypt = true 8 | } 9 | } 10 | 11 | provider "aws" { 12 | region = "eu-north-1" 13 | default_tags { 14 | tags = { 15 | "TerminationDate" = "Permanent", 16 | "Environment" = "Development", 17 | "Team" = "DevOps", 18 | "DeployedBy" = "Terraform", 19 | "OwnerEmail" = "devops@example.com" 20 | "DeploymentPrefix" = "demo-terraform" 21 | } 22 | } 23 | } 24 | 25 | module "tf_backend" { 26 | source = "../../modules/tf-backend/" 27 | s3_bucket_name = "demo-terraform-states-backend" 28 | dynamodb_table_name = "demo-terraform-states-backend" 29 | } -------------------------------------------------------------------------------- /lesson-4/terraform/tf-backend/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/tf-backend/outputs.tf -------------------------------------------------------------------------------- /lesson-4/terraform/tf-backend/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/tf-backend/variables.tf -------------------------------------------------------------------------------- /lesson-4/terraform/vpc/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/vpc/README.md -------------------------------------------------------------------------------- /lesson-4/terraform/vpc/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | bucket = "demo-terraform-states-backend" 4 | key = "vpc/terraform.tfstate" 5 | region = "eu-north-1" 6 | dynamodb_table = "demo-terraform-states-backend" 7 | encrypt = true 8 | } 9 | } 10 | 11 | locals { 12 | deployment_prefix = "demo-terraform" 13 | } 14 | 15 | provider "aws" { 16 | region = "eu-north-1" 17 | default_tags { 18 | tags = { 19 | "TerminationDate" = "Permanent", 20 | "Environment" = "Development", 21 | "Team" = "DevOps", 22 | "DeployedBy" = "Terraform", 23 | "OwnerEmail" = "devops@example.com" 24 | "DeploymentPrefix" = local.deployment_prefix 25 | } 26 | } 27 | } 28 | 29 | module "demo_vpc" { 30 | source = "../../modules/vpc/" 31 | cidr = "10.10.0.0" 32 | deployment_prefix = local.deployment_prefix 33 | } -------------------------------------------------------------------------------- /lesson-4/terraform/vpc/outputs.tf: -------------------------------------------------------------------------------- 1 | # VPC 2 | output "vpc_id" { 3 | description = "The ID of the VPC" 4 | value = module.demo_vpc.vpc_id 5 | } 6 | 7 | output "public_subnets" { 8 | description = "List of IDs of public subnets" 9 | value = module.demo_vpc.public_subnets 10 | } 11 | -------------------------------------------------------------------------------- /lesson-4/terraform/vpc/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-4/terraform/vpc/variables.tf -------------------------------------------------------------------------------- /lesson-4/terragrunt/ec2/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "git::git@github.com:terraform-aws-modules/terraform-aws-ec2-instance.git//.?ref=v4.0.0" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | dependency "vpc" { 11 | config_path = "../vpc/" 12 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"] # Configure mock outputs for the "init", "validate", "plan" commands that are returned when there are no outputs available (e.g the module hasn't been applied yet.) 13 | mock_outputs = { 14 | public_subnets = ["subnet-fake"] 15 | } 16 | } 17 | 18 | dependency "sg" { 19 | config_path = "../sg/" 20 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"] 21 | mock_outputs = { 22 | sg_id = "sg-fake-id" 23 | } 24 | } 25 | 26 | inputs = { 27 | name = "${include.root.inputs.deployment_prefix}-bastion-host" 28 | instance_type = "t3.micro" 29 | ami = "ami-08bdc08970fcbd34a" 30 | vpc_security_group_ids = [dependency.sg.outputs.sg_id] 31 | subnet_id = dependency.vpc.outputs.public_subnets[0] 32 | tags = { 33 | Name = "${include.root.locals.deployment_prefix}-bastion-host" 34 | } 35 | } -------------------------------------------------------------------------------- /lesson-4/terragrunt/sg/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "../../modules//sg/" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | } 8 | 9 | dependency "vpc" { 10 | config_path = "../vpc/" 11 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"] # Configure mock outputs for the "init", "validate", "plan" commands that are returned when there are no outputs available (e.g the module hasn't been applied yet.) 12 | mock_outputs = { 13 | vpc_id = "vpc-fake-id" 14 | } 15 | } 16 | 17 | inputs = { 18 | vpc_id = dependency.vpc.outputs.vpc_id 19 | allowed_cidr_blocks = ["10.10.0.0/16", "192.168.0.0/16"] 20 | } -------------------------------------------------------------------------------- /lesson-4/terragrunt/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | # Configure Terragrunt to automatically store tfstate files in an S3 bucket 2 | remote_state { 3 | backend = "s3" 4 | generate = { 5 | path = "backend.tf" 6 | if_exists = "overwrite_terragrunt" 7 | } 8 | config = { 9 | bucket = "demo-terragrunt-states-backend" 10 | key = "${path_relative_to_include()}/terraform.tfstate" 11 | region = local.aws_region 12 | encrypt = true 13 | dynamodb_table = "demo-terragrunt-states-backend" 14 | } 15 | } 16 | 17 | # Generate an AWS provider block 18 | generate "provider" { 19 | path = "provider.tf" 20 | if_exists = "overwrite_terragrunt" 21 | contents = <> $GITHUB_ENV 91 | terragrunt run-all plan -no-color >> $GITHUB_ENV 92 | echo 'EOF' >> $GITHUB_ENV 93 | continue-on-error: true 94 | 95 | - uses: actions/github-script@0.9.0 96 | if: github.event_name == 'pull_request' 97 | with: 98 | github-token: ${{ secrets.GITHUB_TOKEN }} 99 | script: | 100 | const output = `#### Terragrunt Format and Style 🖌 \`${{ steps.fmt.outcome }}\` 101 | #### Terragrunt Initialization ⚙️ \`${{ steps.init.outcome }}\` 102 | #### Terragrunt Validation 🤖 \`${{ steps.validate.outcome }}\` 103 | #### Terragrunt Plan 📖 \`${{ steps.plan.outcome }}\` 104 | 105 |
Show Plan 106 | 107 | \`\`\`\n 108 | ${{ env.PLAN_OUTPUT }} 109 | \`\`\` 110 | 111 |
112 | 113 | Results for commit: ${{ github.event.pull_request.head.sha }} 114 | 115 | *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.WORKING_DIRECTORY }}\`, Workflow: \`${{ github.workflow }}\`*`; 116 | 117 | github.issues.createComment({ 118 | issue_number: context.issue.number, 119 | owner: context.repo.owner, 120 | repo: context.repo.repo, 121 | body: output 122 | }) 123 | 124 | - name: Terragrunt Plan Status 125 | if: steps.plan.outcome == 'failure' 126 | run: exit 1 127 | 128 | - name: Terragrunt Apply 129 | if: github.ref == 'refs/heads/main' && github.event_name == 'push' 130 | run: terragrunt run-all apply --terragrunt-non-interactive 131 | 132 | -------------------------------------------------------------------------------- /lesson-5/README.md: -------------------------------------------------------------------------------- 1 | 2 | Watch the video 3 | 4 | 5 | ```brew install infracost``` 6 | 7 | ```infracost --version``` 8 | 9 | Get API key 10 | 11 | ```infracost register``` 12 | 13 | The key can be retrieved with ```infracost configure get api_key``` 14 | -------------------------------------------------------------------------------- /lesson-5/dev/ec2/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "git::https://github.com/terraform-aws-modules/terraform-aws-ec2-instance.git//.?ref=v4.0.0" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | dependency "vpc" { 11 | config_path = "../vpc/" 12 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "terragrunt-info", "show"] # Configure mock outputs for the "init", "validate", "plan", etc. commands that are returned when there are no outputs available (e.g the module hasn't been applied yet.) 13 | mock_outputs = { 14 | public_subnets = ["subnet-fake"] 15 | } 16 | } 17 | 18 | dependency "sg" { 19 | config_path = "../sg/" 20 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "terragrunt-info", "show"] 21 | mock_outputs = { 22 | sg_id = "sg-fake-id" 23 | } 24 | } 25 | 26 | inputs = { 27 | name = "${include.root.inputs.deployment_prefix}-bastion-host" 28 | instance_type = "t3.micro" 29 | ami = "ami-08bdc08970fcbd34a" 30 | vpc_security_group_ids = [dependency.sg.outputs.sg_id] 31 | subnet_id = dependency.vpc.outputs.public_subnets[0] 32 | tags = { 33 | Name = "${include.root.locals.deployment_prefix}-bastion-host" 34 | } 35 | } -------------------------------------------------------------------------------- /lesson-5/dev/sg/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "../../modules//sg/" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | } 8 | 9 | dependency "vpc" { 10 | config_path = "../vpc/" 11 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "terragrunt-info", "show"] # Configure mock outputs for the "init", "validate", "plan", etc. commands that are returned when there are no outputs available (e.g the module hasn't been applied yet.) 12 | mock_outputs = { 13 | vpc_id = "vpc-fake-id" 14 | } 15 | } 16 | 17 | inputs = { 18 | vpc_id = dependency.vpc.outputs.vpc_id 19 | allowed_cidr_blocks = ["10.10.0.0/16", "192.168.0.0/16"] 20 | } -------------------------------------------------------------------------------- /lesson-5/dev/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | # Configure Terragrunt to automatically store tfstate files in an S3 bucket 2 | remote_state { 3 | backend = "s3" 4 | generate = { 5 | path = "backend.tf" 6 | if_exists = "overwrite_terragrunt" 7 | } 8 | config = { 9 | bucket = "demo-terragrunt-states-backend" 10 | key = "${path_relative_to_include()}/terraform.tfstate" 11 | region = local.aws_region 12 | encrypt = true 13 | dynamodb_table = "demo-terragrunt-states-backend" 14 | } 15 | } 16 | 17 | # Generate an AWS provider block 18 | generate "provider" { 19 | path = "provider.tf" 20 | if_exists = "overwrite_terragrunt" 21 | contents = < $dir/plan.json 54 | planjsons=(${planjsons[@]} "$dir/plan.json") 55 | done 56 | 57 | # Sort the plan JSONs so we get consistent project ordering in the config file 58 | IFS=$'\n' planjsons=($(sort <<<"${planjsons[*]}")) 59 | 60 | # Generate Infracost config file 61 | echo -e "version: 0.1\n\nprojects:\n" > infracost-generated.yml 62 | for planjson in "${planjsons[@]}"; do 63 | echo -e " - path: $planjson" >> infracost-generated.yml 64 | done 65 | 66 | # Infracost CLI commands can be run now 67 | infracost breakdown --config-file=infracost-generated.yml --format=json --out-file=/tmp/infracost.json 68 | 69 | # Posts a comment to the PR using the 'update' behavior. 70 | # This creates a single comment and updates it. The "quietest" option. 71 | # The other valid behaviors are: 72 | # update - Create a single comment and update it. The "quietest" option. 73 | # delete-and-new - Delete previous comments and create a new one. 74 | # new - Create a new cost estimate comment on every push. 75 | # See https://www.infracost.io/docs/features/cli_commands/#comment-on-pull-requests for other options. 76 | - | 77 | infracost comment gitlab --path=/tmp/infracost.json \ 78 | --repo=$CI_PROJECT_PATH \ 79 | --merge-request=$CI_MERGE_REQUEST_IID \ 80 | --gitlab-server-url=$CI_SERVER_URL \ 81 | --gitlab-token=$GITLAB_TOKEN_BOT \ 82 | --behavior=new 83 | - MESSAGE=$(cat pre-plan.txt) 84 | - >- 85 | cat <> plan.txt 86 | 87 | ###### Terragrunt Status: 88 | 89 |
Show Plan 90 | 91 | 92 | \`\`\`bash$MESSAGE 93 | 94 | \`\`\` 95 | 96 |
97 | 98 | 99 | Results for commit: $CI_COMMIT_SHA 100 | 101 | 102 | *Pusher:* **_\`\`\`$CI_COMMIT_AUTHOR\`\`\`_**,\\ 103 | 104 | *Working Directory:* **_\`\`\`$WORKING_DIRECTORY\`\`\`_**,\\ 105 | 106 | *Job name:* **_\`\`\`$CI_JOB_NAME\`\`\`_**,\\ 107 | 108 | *Terraform version:* **_\`\`\`$(terraform --version -json)\`\`\`_**,\\ 109 | 110 | *Terragrunt version:* **_\`\`\`$(terragrunt --version)\`\`\`_**,\\ 111 | 112 | *Infracost version:* **_\`\`\`$(infracost --version)\`\`\`_**,\\ 113 | 114 | *AWS CLI version:* **_\`\`\`$(aws --version)\`\`\`_** 115 | 116 | EOF 117 | - >- 118 | curl -X POST -g -H "PRIVATE-TOKEN: ${GITLAB_TOKEN_BOT}" 119 | --data-urlencode "body@plan.txt" 120 | "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/discussions" 121 | rules: 122 | - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH 123 | 124 | terragrunt-apply: 125 | before_script: 126 | - !reference [.common_config, before_script] 127 | stage: apply 128 | script: 129 | - !reference [.common_config, script] 130 | - terragrunt run-all apply --terragrunt-non-interactive 131 | rules: 132 | - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH 133 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/antonbabenko/pre-commit-terraform 3 | rev: v1.81.0 4 | hooks: 5 | - id: terragrunt_fmt 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v4.4.0 8 | hooks: 9 | - id: check-merge-conflict 10 | - id: end-of-file-fixer 11 | - id: trailing-whitespace 12 | - id: detect-aws-credentials 13 | - id: detect-private-key 14 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/README.md: -------------------------------------------------------------------------------- 1 | # Terraform IAC Non-Production 2 | 3 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/ecr/project-bar/myapp-1/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "${include.root.locals.source_url}//modules/ecr?ref=${include.root.locals.source_version}" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | dependency "kms" { 11 | config_path = "../../../kms/" 12 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 13 | mock_outputs = { 14 | kms_deployment_key_arn = "arn:aws:kms:eu-west-1:123345678900:key/fake-kms-key" 15 | } 16 | } 17 | 18 | inputs = { 19 | ecr_name = "dev/project-bar/myapp-1" 20 | image_tag_mutability = "IMMUTABLE" 21 | kms_key_id = dependency.kms.outputs.kms_deployment_key_arn 22 | 23 | create_ecr_cache_repository = false 24 | number_of_days_to_keep_cache_images = 14 25 | 26 | create_ecr_repository_policy = false 27 | } 28 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/ecr/project-bar/myapp-2/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "${include.root.locals.source_url}//modules/ecr?ref=${include.root.locals.source_version}" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | dependency "kms" { 11 | config_path = "../../../kms/" 12 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 13 | mock_outputs = { 14 | kms_deployment_key_arn = "arn:aws:kms:eu-west-1:123345678900:key/fake-kms-key" 15 | } 16 | } 17 | 18 | inputs = { 19 | ecr_name = "dev/project-bar/myapp-2" 20 | image_tag_mutability = "IMMUTABLE" 21 | kms_key_id = dependency.kms.outputs.kms_deployment_key_arn 22 | 23 | create_ecr_cache_repository = false 24 | number_of_days_to_keep_cache_images = 14 25 | 26 | create_ecr_repository_policy = false 27 | } 28 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/ecr/project-foo/myapp-1/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "${include.root.locals.source_url}//modules/ecr?ref=${include.root.locals.source_version}" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | dependency "kms" { 11 | config_path = "../../../kms/" 12 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 13 | mock_outputs = { 14 | kms_deployment_key_arn = "arn:aws:kms:eu-west-1:123345678900:key/fake-kms-key" 15 | } 16 | } 17 | 18 | inputs = { 19 | ecr_name = "dev/project-foo/myapp-1" 20 | image_tag_mutability = "IMMUTABLE" 21 | kms_key_id = dependency.kms.outputs.kms_deployment_key_arn 22 | 23 | create_ecr_cache_repository = false 24 | number_of_days_to_keep_cache_images = 14 25 | 26 | create_ecr_repository_policy = false 27 | } 28 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/ecr/project-foo/myapp-2/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "${include.root.locals.source_url}//modules/ecr?ref=${include.root.locals.source_version}" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | dependency "kms" { 11 | config_path = "../../../kms/" 12 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 13 | mock_outputs = { 14 | kms_deployment_key_arn = "arn:aws:kms:eu-west-1:123345678900:key/fake-kms-key" 15 | } 16 | } 17 | 18 | inputs = { 19 | ecr_name = "dev/project-foo/myapp-2" 20 | image_tag_mutability = "IMMUTABLE" 21 | kms_key_id = dependency.kms.outputs.kms_deployment_key_arn 22 | 23 | create_ecr_cache_repository = false 24 | number_of_days_to_keep_cache_images = 14 25 | 26 | create_ecr_repository_policy = false 27 | } 28 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/eks/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "${include.root.locals.source_url}//modules/eks?ref=${include.root.locals.source_version}" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | dependency "vpc" { 11 | config_path = "../networking/vpc/" 12 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 13 | mock_outputs = { 14 | vpc_id = "fake-vpc-id" 15 | private_subnets = ["fake-db-subnet-ids"] 16 | } 17 | } 18 | 19 | dependency "sg" { 20 | config_path = "../networking/sg/" 21 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 22 | mock_outputs = { 23 | all_worker_node_groups_sg_id = "fake-sg-ids" 24 | } 25 | } 26 | 27 | dependency "kms" { 28 | config_path = "../kms/" 29 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 30 | mock_outputs = { 31 | kms_deployment_key_arn = "arn:aws:kms:eu-west-1:123345678900:key/fake-kms-key" 32 | } 33 | } 34 | 35 | inputs = { 36 | cluster_name = include.root.locals.eks_cluster_name 37 | vpc_id = dependency.vpc.outputs.vpc_id 38 | private_subnets_ids = dependency.vpc.outputs.private_subnets 39 | additional_eks_managed_node_sg_ids = [dependency.sg.outputs.all_worker_node_groups_sg_id] 40 | kms_key_id = dependency.kms.outputs.kms_deployment_key_arn 41 | cluster_version = "1.27" 42 | mgmt_instance_types = ["t3.xlarge"] 43 | mgmt_min_size = 2 44 | mgmt_max_size = 2 45 | mgmt_desired_size = 2 46 | create_cloudwatch_log_group = false 47 | cloudwatch_log_group_retention_in_days = 30 48 | cluster_enabled_log_types = [] # For more information, see Amazon EKS Control Plane Logging documentation (https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html) 49 | } 50 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/kms/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "${include.root.locals.source_url}//modules/kms?ref=${include.root.locals.source_version}" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | inputs = { 11 | aws_iam_service_linked_role_autoscaling = false 12 | } 13 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/networking/sg/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "${include.root.locals.source_url}//modules/networking/sg?ref=${include.root.locals.source_version}" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | dependency "vpc" { 11 | config_path = "../vpc" 12 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 13 | mock_outputs = { 14 | vpc_id = "fake-vpc-id" 15 | vpc_cidr_block = "10.0.0.0/16" 16 | } 17 | } 18 | 19 | inputs = { 20 | vpc_id = dependency.vpc.outputs.vpc_id 21 | ssh_ingress_cidr_blocks = [dependency.vpc.outputs.vpc_cidr_block] 22 | } 23 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/networking/vpc/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "${include.root.locals.source_url}//modules/networking/vpc?ref=${include.root.locals.source_version}" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | inputs = { 11 | cidr = "10.20.0.0" 12 | single_nat_gateway = true 13 | one_nat_gateway_per_az = false 14 | } 15 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/rds/demo/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | terraform { 2 | source = "${include.root.locals.source_url}//modules/rds/demo?ref=${include.root.locals.source_version}" 3 | } 4 | 5 | include "root" { 6 | path = find_in_parent_folders() 7 | expose = true 8 | } 9 | 10 | dependency "vpc" { 11 | config_path = "../../networking/vpc/" 12 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 13 | mock_outputs_merge_strategy_with_state = "shallow" 14 | mock_outputs = { 15 | vpc_id = "fake-vpc-id" 16 | database_subnet_group = "fake-database-subnet-group-id" 17 | } 18 | } 19 | 20 | dependency "sg" { 21 | config_path = "../../networking/sg/" 22 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 23 | mock_outputs = { 24 | all_worker_node_groups_sg_id = "fake-sg-ids" 25 | } 26 | } 27 | 28 | dependency "kms" { 29 | config_path = "../../kms/" 30 | mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "providers", "terragrunt-info", "show"] 31 | mock_outputs = { 32 | kms_deployment_key_arn = "arn:aws:kms:eu-west-1:123345678900:key/fake-kms-key" 33 | } 34 | } 35 | 36 | inputs = { 37 | vpc_id = dependency.vpc.outputs.vpc_id 38 | database_subnet_group = dependency.vpc.outputs.database_subnet_group 39 | all_worker_node_groups_sg_id = dependency.sg.outputs.all_worker_node_groups_sg_id 40 | kms_key_id = dependency.kms.outputs.kms_deployment_key_arn 41 | engine = "mysql" 42 | engine_version = "8.0.32" 43 | family = "mysql8.0" 44 | major_engine_version = "8.0" 45 | instance_class = "db.t4g.small" 46 | allocated_storage = 30 47 | max_allocated_storage = 200 48 | multi_az = false 49 | deletion_protection = false 50 | add_extra_cidr_blocks = false 51 | extra_cidr_blocks = [] # Example: ["10.242.2.0/24", "10.246.110.0/24"] 52 | } 53 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-iac-non-prod/dev/main/terragrunt.hcl: -------------------------------------------------------------------------------- 1 | locals { 2 | source_url = "git::https://gitlab.com/bakavets/terraform-modules.git" 3 | source_version = "v0.2.1" 4 | deployment_prefix = "main-dev" 5 | aws_region = "eu-central-1" 6 | eks_cluster_name = "${local.deployment_prefix}-eks-cluster" 7 | default_tags = { 8 | "TerminationDate" = "Permanent", 9 | "Environment" = "Development", 10 | "Team" = "DevOps", 11 | "DeployedBy" = "Terraform", 12 | "OwnerEmail" = "bakavets.com@gmail.com" 13 | "DeploymentPrefix" = local.deployment_prefix 14 | } 15 | } 16 | 17 | # Configure Terragrunt to automatically store tfstate files in an S3 bucket 18 | remote_state { 19 | backend = "s3" 20 | generate = { 21 | path = "backend.tf" 22 | if_exists = "overwrite_terragrunt" 23 | } 24 | config = { 25 | bucket = "${local.deployment_prefix}-terraform-states-backend-demo" 26 | key = "${path_relative_to_include()}/terraform.tfstate" 27 | region = local.aws_region 28 | encrypt = true 29 | dynamodb_table = "${local.deployment_prefix}-terraform-states-backend-demo" 30 | s3_bucket_tags = local.default_tags 31 | dynamodb_table_tags = local.default_tags 32 | } 33 | } 34 | 35 | # Generate an AWS provider block 36 | generate "provider" { 37 | path = "provider.tf" 38 | if_exists = "overwrite_terragrunt" 39 | contents = < 20 | --args=--exclude-downloaded-modules=true 21 | -e aws-rds-enable-performance-insights 22 | # - id: terrascan 23 | # args: 24 | # - '--args=--verbose' 25 | # - '--args=--skip-rules="AC_AWS_0057,AC_AWS_0053,AC_AWS_0454,AC_AWS_0369"' 26 | - id: terraform_tflint 27 | args: 28 | - '--args=--only=terraform_deprecated_interpolation' 29 | - '--args=--only=terraform_deprecated_index' 30 | - '--args=--only=terraform_unused_declarations' 31 | - '--args=--only=terraform_comment_syntax' 32 | - '--args=--only=terraform_documented_outputs' 33 | - '--args=--only=terraform_documented_variables' 34 | - '--args=--only=terraform_typed_variables' 35 | - '--args=--only=terraform_module_pinned_source' 36 | - '--args=--only=terraform_naming_convention' 37 | - '--args=--only=terraform_required_version' 38 | - '--args=--only=terraform_required_providers' 39 | - '--args=--only=terraform_standard_module_structure' 40 | - '--args=--only=terraform_workspace_remote' 41 | - repo: https://github.com/pre-commit/pre-commit-hooks 42 | rev: v4.4.0 43 | hooks: 44 | - id: check-merge-conflict 45 | - id: end-of-file-fixer 46 | - id: trailing-whitespace 47 | - id: detect-aws-credentials 48 | - id: detect-private-key 49 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Modules 2 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/docs/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-6-7-8/terraform-modules/docs/README.md -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/examples/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakavets/terraform-lessons/71e67271f49163f3910ebb93b9f489cefe7214d1/lesson-6-7-8/terraform-modules/examples/README.md -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/ecr/README.md: -------------------------------------------------------------------------------- 1 | # ecr 2 | 3 | 4 | ## Requirements 5 | 6 | | Name | Version | 7 | |------|---------| 8 | | [terraform](#requirement\_terraform) | >= 1.0.2 | 9 | | [aws](#requirement\_aws) | >= 4.6 | 10 | 11 | ## Providers 12 | 13 | | Name | Version | 14 | |------|---------| 15 | | [aws](#provider\_aws) | >= 4.6 | 16 | 17 | ## Modules 18 | 19 | No modules. 20 | 21 | ## Resources 22 | 23 | | Name | Type | 24 | |------|------| 25 | | [aws_ecr_lifecycle_policy.template_cache_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_lifecycle_policy) | resource | 26 | | [aws_ecr_repository.template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource | 27 | | [aws_ecr_repository.template_cache](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource | 28 | | [aws_ecr_repository_policy.template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository_policy) | resource | 29 | 30 | ## Inputs 31 | 32 | | Name | Description | Type | Default | Required | 33 | |------|-------------|------|---------|:--------:| 34 | | [create\_ecr\_cache\_repository](#input\_create\_ecr\_cache\_repository) | Determines whether to create cache ECR repository or not | `bool` | `false` | no | 35 | | [create\_ecr\_repository\_policy](#input\_create\_ecr\_repository\_policy) | Determines whether to create ECR repository policy or not | `bool` | `false` | no | 36 | | [deployment\_prefix](#input\_deployment\_prefix) | Prefix of the deployment | `string` | n/a | yes | 37 | | [ecr\_name](#input\_ecr\_name) | ECR name for service | `string` | n/a | yes | 38 | | [ecr\_repository\_policy](#input\_ecr\_repository\_policy) | Elastic Container Registry Repository Policy. | `string` | `""` | no | 39 | | [image\_tag\_mutability](#input\_image\_tag\_mutability) | The tag mutability setting for the repository. Must be one of: MUTABLE or IMMUTABLE | `string` | `"IMMUTABLE"` | no | 40 | | [kms\_key\_id](#input\_kms\_key\_id) | The ARN KMS key | `string` | n/a | yes | 41 | | [number\_of\_days\_to\_keep\_cache\_images](#input\_number\_of\_days\_to\_keep\_cache\_images) | A number of days to keep cache images. | `number` | `14` | no | 42 | 43 | ## Outputs 44 | 45 | No outputs. 46 | 47 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/ecr/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ecr_repository" "template" { 2 | name = var.ecr_name 3 | image_tag_mutability = var.image_tag_mutability 4 | encryption_configuration { 5 | encryption_type = "KMS" 6 | kms_key = var.kms_key_id 7 | } 8 | image_scanning_configuration { 9 | scan_on_push = true 10 | } 11 | tags = { 12 | "Name" = var.ecr_name 13 | "Type" = "Elastic Container Registry" 14 | "Description" = "Registry for deployment related to ${var.deployment_prefix}" 15 | } 16 | } 17 | 18 | resource "aws_ecr_repository_policy" "template" { 19 | count = var.create_ecr_repository_policy ? 1 : 0 20 | 21 | repository = aws_ecr_repository.template.name 22 | policy = var.ecr_repository_policy 23 | } 24 | 25 | resource "aws_ecr_repository" "template_cache" { 26 | count = var.create_ecr_cache_repository ? 1 : 0 27 | 28 | name = "${var.ecr_name}/cache" 29 | image_tag_mutability = "MUTABLE" 30 | encryption_configuration { 31 | encryption_type = "KMS" 32 | kms_key = var.kms_key_id 33 | } 34 | tags = { 35 | "Name" = var.ecr_name 36 | "Type" = "Elastic Container Registry" 37 | "Description" = "Registry for deployment related to ${var.deployment_prefix}" 38 | } 39 | } 40 | 41 | resource "aws_ecr_lifecycle_policy" "template_cache_policy" { 42 | count = var.create_ecr_cache_repository ? 1 : 0 43 | 44 | repository = aws_ecr_repository.template_cache[0].name 45 | 46 | policy = < 3 | ## Requirements 4 | 5 | | Name | Version | 6 | |------|---------| 7 | | [terraform](#requirement\_terraform) | >= 1.0.2 | 8 | | [aws](#requirement\_aws) | >= 4.47 | 9 | | [kubernetes](#requirement\_kubernetes) | >= 2.4.1 | 10 | | [tls](#requirement\_tls) | ~> 3.0 | 11 | 12 | ## Providers 13 | 14 | No providers. 15 | 16 | ## Modules 17 | 18 | | Name | Source | Version | 19 | |------|--------|---------| 20 | | [eks](#module\_eks) | terraform-aws-modules/eks/aws | 19.15.3 | 21 | 22 | ## Resources 23 | 24 | No resources. 25 | 26 | ## Inputs 27 | 28 | | Name | Description | Type | Default | Required | 29 | |------|-------------|------|---------|:--------:| 30 | | [additional\_eks\_managed\_node\_sg\_ids](#input\_additional\_eks\_managed\_node\_sg\_ids) | K8s Nodes SG IDs | `list(string)` | n/a | yes | 31 | | [cloudwatch\_log\_group\_retention\_in\_days](#input\_cloudwatch\_log\_group\_retention\_in\_days) | Number of days to retain log events. Default retention - 30 days | `number` | `30` | no | 32 | | [cluster\_enabled\_log\_types](#input\_cluster\_enabled\_log\_types) | A list of the desired control plane logs to enable. For more information, see Amazon EKS Control Plane Logging documentation (https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html) | `list(string)` | `[]` | no | 33 | | [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | n/a | yes | 34 | | [cluster\_version](#input\_cluster\_version) | Kubernetes `.` version to use for the EKS cluster (i.e.: `1.24`) | `string` | n/a | yes | 35 | | [create\_cloudwatch\_log\_group](#input\_create\_cloudwatch\_log\_group) | Determines whether a log group is created by this module for the cluster logs. If not, AWS will automatically create one if logging is enabled | `bool` | `false` | no | 36 | | [deployment\_prefix](#input\_deployment\_prefix) | Prefix of the deployment | `string` | n/a | yes | 37 | | [kms\_key\_id](#input\_kms\_key\_id) | The KMS key to use when encrypting the root storage device, EKS Secrets, SSH Key pair etc. | `string` | n/a | yes | 38 | | [mgmt\_desired\_size](#input\_mgmt\_desired\_size) | Desired worker capacity in the autoscaling group | `number` | n/a | yes | 39 | | [mgmt\_instance\_types](#input\_mgmt\_instance\_types) | The ALL types of EC2 instances MUST have RAM: 16.0GiB and CPU: 4vCPUs. Make sure that default EC2 insatnce types exist within selected AWS region. | `list(string)` | n/a | yes | 40 | | [mgmt\_max\_size](#input\_mgmt\_max\_size) | Maximum worker capacity in the autoscaling group | `number` | n/a | yes | 41 | | [mgmt\_min\_size](#input\_mgmt\_min\_size) | Minimum worker capacity in the autoscaling group. NOTE: Change in this paramater will affect the asg\_desired\_capacity, like changing its value to 2 will change asg\_desired\_capacity value to 2 but bringing back it to 1 will not affect the asg\_desired\_capacity. | `number` | n/a | yes | 42 | | [private\_subnets\_ids](#input\_private\_subnets\_ids) | A list of VPC Private subnet IDs | `list(string)` | n/a | yes | 43 | | [vpc\_id](#input\_vpc\_id) | VPC ID | `string` | n/a | yes | 44 | 45 | ## Outputs 46 | 47 | | Name | Description | 48 | |------|-------------| 49 | | [cluster\_arn](#output\_cluster\_arn) | The Amazon Resource Name (ARN) of the cluster | 50 | | [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64 encoded certificate data required to communicate with the cluster | 51 | | [cluster\_endpoint](#output\_cluster\_endpoint) | Endpoint for EKS control plane. | 52 | | [cluster\_id](#output\_cluster\_id) | EKS cluster ID. | 53 | | [cluster\_oidc\_issuer\_url](#output\_cluster\_oidc\_issuer\_url) | The URL on the EKS cluster OIDC Issuer. | 54 | | [cluster\_security\_group\_id](#output\_cluster\_security\_group\_id) | Security group ids attached to the cluster control plane. | 55 | | [eks\_mng\_management\_iam\_role\_arn](#output\_eks\_mng\_management\_iam\_role\_arn) | IAM Role ARN of EKS Managed Node group. | 56 | | [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | The ARN of the OIDC Provider. | 57 | 58 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/eks/main.tf: -------------------------------------------------------------------------------- 1 | provider "kubernetes" { 2 | host = module.eks.cluster_endpoint 3 | cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) 4 | 5 | exec { 6 | api_version = "client.authentication.k8s.io/v1beta1" 7 | command = "aws" 8 | # This requires the awscli to be installed locally where Terraform is executed 9 | args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name] 10 | } 11 | } 12 | 13 | locals { 14 | cluster_name = var.cluster_name 15 | } 16 | 17 | module "eks" { 18 | source = "terraform-aws-modules/eks/aws" 19 | version = "19.15.3" 20 | cluster_name = local.cluster_name 21 | cluster_version = var.cluster_version 22 | vpc_id = var.vpc_id 23 | subnet_ids = var.private_subnets_ids 24 | enable_irsa = true 25 | cluster_endpoint_private_access = true 26 | cluster_endpoint_public_access = true 27 | 28 | cluster_addons = { 29 | coredns = { 30 | most_recent = true 31 | } 32 | kube-proxy = { 33 | most_recent = true 34 | } 35 | vpc-cni = { 36 | most_recent = true 37 | } 38 | } 39 | 40 | create_cloudwatch_log_group = var.create_cloudwatch_log_group 41 | cloudwatch_log_group_retention_in_days = var.cloudwatch_log_group_retention_in_days 42 | cluster_enabled_log_types = var.cluster_enabled_log_types 43 | 44 | eks_managed_node_group_defaults = { 45 | vpc_security_group_ids = var.additional_eks_managed_node_sg_ids 46 | } 47 | 48 | manage_aws_auth_configmap = true 49 | 50 | create_kms_key = false 51 | cluster_encryption_config = { 52 | provider_key_arn = var.kms_key_id 53 | resources = ["secrets"] 54 | } 55 | 56 | tags = { 57 | "Name" = local.cluster_name 58 | "Type" = "Kubernetes Service" 59 | "K8s Description" = "Kubernetes for deployment related to ${var.deployment_prefix}" 60 | } 61 | 62 | # EKS Managed Node Group(s) 63 | eks_managed_node_groups = { 64 | management = { 65 | min_size = var.mgmt_min_size 66 | max_size = var.mgmt_max_size 67 | desired_size = var.mgmt_desired_size 68 | 69 | instance_types = var.mgmt_instance_types 70 | capacity_type = "ON_DEMAND" 71 | 72 | block_device_mappings = { 73 | xvda = { 74 | device_name = "/dev/xvda" 75 | ebs = { 76 | volume_size = 50 77 | volume_type = "gp3" 78 | encrypted = true 79 | kms_key_id = var.kms_key_id 80 | delete_on_termination = true 81 | } 82 | } 83 | } 84 | labels = { 85 | "node.k8s/role" = "management" 86 | } 87 | } 88 | } 89 | 90 | node_security_group_additional_rules = { 91 | ingress_self_all = { 92 | description = "Allow nodes to communicate with each other (all ports/protocols)." 93 | protocol = "-1" 94 | from_port = 0 95 | to_port = 0 96 | type = "ingress" 97 | self = true 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/eks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "cluster_id" { 2 | description = "EKS cluster ID." 3 | value = module.eks.cluster_id 4 | } 5 | 6 | output "cluster_endpoint" { 7 | description = "Endpoint for EKS control plane." 8 | value = module.eks.cluster_endpoint 9 | } 10 | 11 | output "cluster_security_group_id" { 12 | description = "Security group ids attached to the cluster control plane." 13 | value = module.eks.cluster_security_group_id 14 | } 15 | 16 | output "cluster_oidc_issuer_url" { 17 | description = "The URL on the EKS cluster OIDC Issuer." 18 | value = module.eks.cluster_oidc_issuer_url 19 | } 20 | 21 | output "cluster_certificate_authority_data" { 22 | description = "Base64 encoded certificate data required to communicate with the cluster" 23 | value = module.eks.cluster_certificate_authority_data 24 | } 25 | 26 | output "eks_mng_management_iam_role_arn" { 27 | description = "IAM Role ARN of EKS Managed Node group." 28 | value = module.eks.eks_managed_node_groups["management"].iam_role_arn 29 | } 30 | 31 | output "oidc_provider_arn" { 32 | description = "The ARN of the OIDC Provider." 33 | value = module.eks.oidc_provider_arn 34 | } 35 | 36 | output "cluster_arn" { 37 | description = "The Amazon Resource Name (ARN) of the cluster" 38 | value = module.eks.cluster_arn 39 | } 40 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/eks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "deployment_prefix" { 2 | description = "Prefix of the deployment" 3 | type = string 4 | } 5 | 6 | variable "vpc_id" { 7 | description = "VPC ID" 8 | type = string 9 | } 10 | 11 | variable "private_subnets_ids" { 12 | description = "A list of VPC Private subnet IDs" 13 | type = list(string) 14 | } 15 | 16 | variable "additional_eks_managed_node_sg_ids" { 17 | description = "K8s Nodes SG IDs" 18 | type = list(string) 19 | } 20 | 21 | variable "kms_key_id" { 22 | description = "The KMS key to use when encrypting the root storage device, EKS Secrets, SSH Key pair etc." 23 | type = string 24 | } 25 | 26 | variable "mgmt_instance_types" { 27 | description = "The ALL types of EC2 instances MUST have RAM: 16.0GiB and CPU: 4vCPUs. Make sure that default EC2 insatnce types exist within selected AWS region." 28 | type = list(string) 29 | } 30 | 31 | variable "mgmt_min_size" { 32 | description = "Minimum worker capacity in the autoscaling group. NOTE: Change in this paramater will affect the asg_desired_capacity, like changing its value to 2 will change asg_desired_capacity value to 2 but bringing back it to 1 will not affect the asg_desired_capacity." 33 | type = number 34 | } 35 | 36 | variable "mgmt_max_size" { 37 | description = "Maximum worker capacity in the autoscaling group" 38 | type = number 39 | } 40 | 41 | variable "mgmt_desired_size" { 42 | description = "Desired worker capacity in the autoscaling group" 43 | type = number 44 | } 45 | 46 | ################################################################################ 47 | # CloudWatch Log Group 48 | ################################################################################ 49 | 50 | variable "create_cloudwatch_log_group" { 51 | description = "Determines whether a log group is created by this module for the cluster logs. If not, AWS will automatically create one if logging is enabled" 52 | type = bool 53 | default = false 54 | } 55 | 56 | variable "cloudwatch_log_group_retention_in_days" { 57 | description = "Number of days to retain log events. Default retention - 30 days" 58 | type = number 59 | default = 30 60 | } 61 | 62 | variable "cluster_enabled_log_types" { 63 | description = "A list of the desired control plane logs to enable. For more information, see Amazon EKS Control Plane Logging documentation (https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html)" 64 | type = list(string) 65 | default = [] 66 | } 67 | 68 | 69 | variable "cluster_name" { 70 | description = "Name of the EKS cluster" 71 | type = string 72 | } 73 | 74 | variable "cluster_version" { 75 | description = "Kubernetes `.` version to use for the EKS cluster (i.e.: `1.24`)" 76 | type = string 77 | } 78 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/eks/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.2" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.47" 8 | } 9 | kubernetes = { 10 | source = "hashicorp/kubernetes" 11 | version = ">= 2.4.1" 12 | } 13 | tls = { 14 | source = "hashicorp/tls" 15 | version = "~> 3.0" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/kms/README.md: -------------------------------------------------------------------------------- 1 | # kms 2 | 3 | 4 | ## Requirements 5 | 6 | | Name | Version | 7 | |------|---------| 8 | | [terraform](#requirement\_terraform) | >= 1.0.2 | 9 | | [aws](#requirement\_aws) | 3.52.0 | 10 | 11 | ## Providers 12 | 13 | | Name | Version | 14 | |------|---------| 15 | | [aws](#provider\_aws) | 3.52.0 | 16 | 17 | ## Modules 18 | 19 | No modules. 20 | 21 | ## Resources 22 | 23 | | Name | Type | 24 | |------|------| 25 | | [aws_iam_service_linked_role.autoscaling](https://registry.terraform.io/providers/hashicorp/aws/3.52.0/docs/resources/iam_service_linked_role) | resource | 26 | | [aws_kms_alias.kms_deployment_key](https://registry.terraform.io/providers/hashicorp/aws/3.52.0/docs/resources/kms_alias) | resource | 27 | | [aws_kms_key.kms_deployment_key](https://registry.terraform.io/providers/hashicorp/aws/3.52.0/docs/resources/kms_key) | resource | 28 | | [aws_caller_identity.account](https://registry.terraform.io/providers/hashicorp/aws/3.52.0/docs/data-sources/caller_identity) | data source | 29 | 30 | ## Inputs 31 | 32 | | Name | Description | Type | Default | Required | 33 | |------|-------------|------|---------|:--------:| 34 | | [aws\_iam\_service\_linked\_role\_autoscaling](#input\_aws\_iam\_service\_linked\_role\_autoscaling) | Controls if AWS IAM Service linked role Autoscaling should be created. | `bool` | `false` | no | 35 | | [deployment\_prefix](#input\_deployment\_prefix) | Prefix of the deployment. | `string` | n/a | yes | 36 | 37 | ## Outputs 38 | 39 | | Name | Description | 40 | |------|-------------| 41 | | [kms\_deployment\_key\_arn](#output\_kms\_deployment\_key\_arn) | KMS Key ARN. | 42 | 43 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/kms/main.tf: -------------------------------------------------------------------------------- 1 | data "aws_caller_identity" "account" {} 2 | 3 | resource "aws_kms_key" "kms_deployment_key" { 4 | description = "AWS KMS key used to encrypt AWS resources (e.g. Volumes, EKS Secrets, etc.)." 5 | key_usage = "ENCRYPT_DECRYPT" 6 | customer_master_key_spec = "SYMMETRIC_DEFAULT" 7 | enable_key_rotation = true 8 | # The following snippet shows the policy statement that gives an example AWS account full access to a KMS key. This policy statement lets the account use IAM policies, along with key policies, to control access to the KMS key. 9 | policy = < 3 | ## Requirements 4 | 5 | | Name | Version | 6 | |------|---------| 7 | | [terraform](#requirement\_terraform) | >= 1.0.2 | 8 | | [aws](#requirement\_aws) | >= 3.63.0 | 9 | 10 | ## Providers 11 | 12 | | Name | Version | 13 | |------|---------| 14 | | [aws](#provider\_aws) | >= 3.63.0 | 15 | 16 | ## Modules 17 | 18 | No modules. 19 | 20 | ## Resources 21 | 22 | | Name | Type | 23 | |------|------| 24 | | [aws_security_group.all_worker_node_groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | 25 | 26 | ## Inputs 27 | 28 | | Name | Description | Type | Default | Required | 29 | |------|-------------|------|---------|:--------:| 30 | | [deployment\_prefix](#input\_deployment\_prefix) | Prefix of the deployment | `string` | n/a | yes | 31 | | [ssh\_ingress\_cidr\_blocks](#input\_ssh\_ingress\_cidr\_blocks) | Allowed CIDR blocks for the SSH for the worker K8s Nodes. | `list(string)` | n/a | yes | 32 | | [vpc\_id](#input\_vpc\_id) | AWS VPC ID | `string` | n/a | yes | 33 | 34 | ## Outputs 35 | 36 | | Name | Description | 37 | |------|-------------| 38 | | [all\_worker\_node\_groups\_sg\_id](#output\_all\_worker\_node\_groups\_sg\_id) | K8s Nodes SG | 39 | 40 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/networking/sg/main.tf: -------------------------------------------------------------------------------- 1 | # Kubernetes worker node SG 2 | resource "aws_security_group" "all_worker_node_groups" { 3 | name = "${var.deployment_prefix}-for-all-node-groups-sg" 4 | vpc_id = var.vpc_id 5 | description = "What does this rule enable" 6 | 7 | ingress { 8 | from_port = 22 9 | to_port = 22 10 | protocol = "tcp" 11 | description = "Inbound traffic only from internal VPC" 12 | cidr_blocks = var.ssh_ingress_cidr_blocks 13 | } 14 | egress { 15 | from_port = 0 16 | to_port = 0 17 | protocol = "-1" 18 | cidr_blocks = ["10.10.0.0/16"] 19 | description = "What does this rule enable" 20 | } 21 | 22 | tags = { 23 | "Name" = "${var.deployment_prefix}-for-all-node-groups-sg" 24 | "Description" = "Inbound traffic only from internal VPC" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/networking/sg/outputs.tf: -------------------------------------------------------------------------------- 1 | output "all_worker_node_groups_sg_id" { 2 | description = "K8s Nodes SG" 3 | value = aws_security_group.all_worker_node_groups.id 4 | } 5 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/networking/sg/variables.tf: -------------------------------------------------------------------------------- 1 | variable "deployment_prefix" { 2 | description = "Prefix of the deployment" 3 | type = string 4 | } 5 | 6 | variable "vpc_id" { 7 | description = "AWS VPC ID" 8 | type = string 9 | } 10 | 11 | variable "ssh_ingress_cidr_blocks" { 12 | description = "Allowed CIDR blocks for the SSH for the worker K8s Nodes." 13 | type = list(string) 14 | } 15 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/networking/sg/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.2" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 3.63.0" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/networking/vpc/README.md: -------------------------------------------------------------------------------- 1 | # vpc 2 | 3 | ## Requirements 4 | 5 | | Name | Version | 6 | |------|---------| 7 | | [terraform](#requirement\_terraform) | >= 1.0.2 | 8 | | [aws](#requirement\_aws) | <= 4.67.0 | 9 | 10 | ## Providers 11 | 12 | | Name | Version | 13 | |------|---------| 14 | | [aws](#provider\_aws) | <= 4.67.0 | 15 | 16 | ## Modules 17 | 18 | | Name | Source | Version | 19 | |------|--------|---------| 20 | | [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | 3.14.2 | 21 | 22 | ## Resources 23 | 24 | | Name | Type | 25 | |------|------| 26 | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | 27 | 28 | ## Inputs 29 | 30 | | Name | Description | Type | Default | Required | 31 | |------|-------------|------|---------|:--------:| 32 | | [cidr](#input\_cidr) | The CIDR block for the VPC. Default value is a valid CIDR, but not acceptable by AWS and should be overridden. | `string` | `"0.0.0.0"` | no | 33 | | [deployment\_prefix](#input\_deployment\_prefix) | Prefix of the deployment | `string` | n/a | yes | 34 | | [one\_nat\_gateway\_per\_az](#input\_one\_nat\_gateway\_per\_az) | Should be true if you want only one NAT Gateway per availability zone. | `bool` | `false` | no | 35 | | [single\_nat\_gateway](#input\_single\_nat\_gateway) | Should be true if you want to provision a single shared NAT Gateway across all of your private networks. | `bool` | `false` | no | 36 | 37 | ## Outputs 38 | 39 | | Name | Description | 40 | |------|-------------| 41 | | [database\_subnet\_group](#output\_database\_subnet\_group) | ID of database subnet group | 42 | | [database\_subnets](#output\_database\_subnets) | List of IDs of database subnets. | 43 | | [intra\_subnets](#output\_intra\_subnets) | List of IDs of intra subnets. | 44 | | [nat\_public\_ips](#output\_nat\_public\_ips) | List of public Elastic IPs created for AWS NAT Gateway | 45 | | [private\_subnet\_arns](#output\_private\_subnet\_arns) | List of ARNs of private subnets | 46 | | [private\_subnets](#output\_private\_subnets) | List of IDs of private subnets. | 47 | | [public\_subnets](#output\_public\_subnets) | List of IDs of public subnets. | 48 | | [vpc\_cidr\_block](#output\_vpc\_cidr\_block) | The CIDR block of the VPC | 49 | | [vpc\_id](#output\_vpc\_id) | The ID of the VPC. | 50 | 51 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/networking/vpc/main.tf: -------------------------------------------------------------------------------- 1 | data "aws_availability_zones" "available" {} 2 | 3 | locals { 4 | cidr_part = trimsuffix(var.cidr, ".0.0") 5 | eks_cluster_name = "${var.deployment_prefix}-eks-cluster" 6 | } 7 | 8 | module "vpc" { 9 | source = "terraform-aws-modules/vpc/aws" 10 | version = "3.14.2" 11 | 12 | name = "${var.deployment_prefix}-vpc" 13 | cidr = "${var.cidr}/16" 14 | azs = data.aws_availability_zones.available.names 15 | private_subnets = ["${local.cidr_part}.0.0/19", "${local.cidr_part}.32.0/19", "${local.cidr_part}.64.0/19"] 16 | public_subnets = ["${local.cidr_part}.96.0/22", "${local.cidr_part}.100.0/22", "${local.cidr_part}.104.0/22"] 17 | database_subnets = ["${local.cidr_part}.108.0/24", "${local.cidr_part}.109.0/24", "${local.cidr_part}.110.0/24"] 18 | intra_subnets = ["${local.cidr_part}.111.0/24", "${local.cidr_part}.112.0/24", "${local.cidr_part}.113.0/24"] 19 | enable_nat_gateway = true 20 | single_nat_gateway = var.single_nat_gateway 21 | one_nat_gateway_per_az = var.one_nat_gateway_per_az 22 | enable_dns_hostnames = true 23 | create_igw = true 24 | create_database_subnet_route_table = true 25 | 26 | tags = { 27 | "Name" = "${var.deployment_prefix}-VPC" 28 | } 29 | 30 | public_subnet_tags = { 31 | "Name" = "public-subnet-${var.deployment_prefix}" 32 | "kubernetes.io/cluster/${local.eks_cluster_name}" = "shared" 33 | "kubernetes.io/role/elb" = "1" 34 | } 35 | 36 | private_subnet_tags = { 37 | "Name" = "private-subnet-${var.deployment_prefix}" 38 | "kubernetes.io/cluster/${local.eks_cluster_name}" = "shared" 39 | "kubernetes.io/role/internal-elb" = "1" 40 | } 41 | 42 | database_subnet_tags = { 43 | "Name" = "database-subnet-${var.deployment_prefix}" 44 | } 45 | 46 | intra_subnet_tags = { 47 | "Name" = "intra-subnet-${var.deployment_prefix}" 48 | } 49 | 50 | intra_route_table_tags = { 51 | "Name" = "intra-route-table-${var.deployment_prefix}" 52 | } 53 | 54 | public_route_table_tags = { 55 | "Name" = "public-route-table-${var.deployment_prefix}" 56 | } 57 | 58 | database_route_table_tags = { 59 | "Name" = "database-route-table-${var.deployment_prefix}" 60 | } 61 | 62 | private_route_table_tags = { 63 | "Name" = "private-route-table-${var.deployment_prefix}" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/networking/vpc/outputs.tf: -------------------------------------------------------------------------------- 1 | # VPC 2 | output "vpc_id" { 3 | description = "The ID of the VPC." 4 | value = module.vpc.vpc_id 5 | } 6 | 7 | # Subnets 8 | output "private_subnets" { 9 | description = "List of IDs of private subnets." 10 | value = module.vpc.private_subnets 11 | } 12 | 13 | output "private_subnet_arns" { 14 | description = "List of ARNs of private subnets" 15 | value = module.vpc.private_subnet_arns 16 | } 17 | 18 | output "public_subnets" { 19 | description = "List of IDs of public subnets." 20 | value = module.vpc.public_subnets 21 | } 22 | 23 | output "database_subnets" { 24 | description = "List of IDs of database subnets." 25 | value = module.vpc.database_subnets 26 | } 27 | 28 | output "intra_subnets" { 29 | description = "List of IDs of intra subnets." 30 | value = module.vpc.intra_subnets 31 | } 32 | 33 | # NAT gateways 34 | output "nat_public_ips" { 35 | description = "List of public Elastic IPs created for AWS NAT Gateway" 36 | value = module.vpc.nat_public_ips 37 | } 38 | 39 | output "vpc_cidr_block" { 40 | description = "The CIDR block of the VPC" 41 | value = module.vpc.vpc_cidr_block 42 | } 43 | 44 | output "database_subnet_group" { 45 | description = "ID of database subnet group" 46 | value = module.vpc.database_subnet_group 47 | } 48 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/networking/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "deployment_prefix" { 2 | description = "Prefix of the deployment" 3 | type = string 4 | } 5 | 6 | variable "cidr" { 7 | description = "The CIDR block for the VPC. Default value is a valid CIDR, but not acceptable by AWS and should be overridden." 8 | type = string 9 | default = "0.0.0.0" 10 | } 11 | 12 | variable "single_nat_gateway" { 13 | description = "Should be true if you want to provision a single shared NAT Gateway across all of your private networks." 14 | type = bool 15 | default = false 16 | } 17 | 18 | variable "one_nat_gateway_per_az" { 19 | description = "Should be true if you want only one NAT Gateway per availability zone." 20 | type = bool 21 | default = false 22 | } 23 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/networking/vpc/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.2" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = "<= 4.67.0" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/rds/demo/README.md: -------------------------------------------------------------------------------- 1 | # Demo 2 | 3 | ## Requirements 4 | 5 | | Name | Version | 6 | |------|---------| 7 | | [terraform](#requirement\_terraform) | >= 1.0.2 | 8 | | [aws](#requirement\_aws) | >= 4.6 | 9 | | [random](#requirement\_random) | >= 3.1 | 10 | 11 | ## Providers 12 | 13 | | Name | Version | 14 | |------|---------| 15 | | [aws](#provider\_aws) | >= 4.6 | 16 | | [random](#provider\_random) | >= 3.1 | 17 | 18 | ## Modules 19 | 20 | | Name | Source | Version | 21 | |------|--------|---------| 22 | | [demo](#module\_demo) | terraform-aws-modules/rds/aws | 5.9.0 | 23 | 24 | ## Resources 25 | 26 | | Name | Type | 27 | |------|------| 28 | | [aws_secretsmanager_secret.demo](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | 29 | | [aws_secretsmanager_secret_version.demo](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | 30 | | [aws_security_group.demo](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | 31 | | [aws_security_group_rule.access_ingress_from_kubernetes_nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | 32 | | [aws_security_group_rule.extra_inbound_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | 33 | | [random_password.master_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | 34 | 35 | ## Inputs 36 | 37 | | Name | Description | Type | Default | Required | 38 | |------|-------------|------|---------|:--------:| 39 | | [add\_extra\_cidr\_blocks](#input\_add\_extra\_cidr\_blocks) | Controls if extra CIDR blocks should be added. | `bool` | `false` | no | 40 | | [all\_worker\_node\_groups\_sg\_id](#input\_all\_worker\_node\_groups\_sg\_id) | The common SG ID of K8s nodes | `string` | n/a | yes | 41 | | [allocated\_storage](#input\_allocated\_storage) | The allocated storage in gigabytes | `string` | n/a | yes | 42 | | [database\_subnet\_group](#input\_database\_subnet\_group) | ID of database subnet group | `string` | n/a | yes | 43 | | [deletion\_protection](#input\_deletion\_protection) | The database can't be deleted when this value is set to true | `bool` | `true` | no | 44 | | [deployment\_prefix](#input\_deployment\_prefix) | Prefix of the deployment | `string` | n/a | yes | 45 | | [engine](#input\_engine) | The database engine to use | `string` | n/a | yes | 46 | | [engine\_version](#input\_engine\_version) | The engine version to use | `string` | n/a | yes | 47 | | [extra\_cidr\_blocks](#input\_extra\_cidr\_blocks) | Extra CIDR blocks to get access to database. | `list(string)` | `[]` | no | 48 | | [family](#input\_family) | The family of the DB parameter group | `string` | n/a | yes | 49 | | [instance\_class](#input\_instance\_class) | The instance type of the RDS instance | `string` | n/a | yes | 50 | | [kms\_key\_id](#input\_kms\_key\_id) | The ARN for the KMS encryption key | `string` | n/a | yes | 51 | | [major\_engine\_version](#input\_major\_engine\_version) | Specifies the major version of the engine that this option group should be associated with | `string` | n/a | yes | 52 | | [max\_allocated\_storage](#input\_max\_allocated\_storage) | Specifies the value for Storage Autoscaling | `number` | n/a | yes | 53 | | [multi\_az](#input\_multi\_az) | Specifies if the RDS instance is multi-AZ | `bool` | `false` | no | 54 | | [my\_password](#input\_my\_password) | My password | `string` | n/a | yes | 55 | | [performance\_insights\_enabled](#input\_performance\_insights\_enabled) | Specifies whether Performance Insights are enabled | `bool` | `false` | no | 56 | | [vpc\_id](#input\_vpc\_id) | The VPC ID where DB cluster should be deployed | `string` | n/a | yes | 57 | 58 | ## Outputs 59 | 60 | | Name | Description | 61 | |------|-------------| 62 | | [db\_instance\_address](#output\_db\_instance\_address) | The address of the RDS instance | 63 | | [db\_instance\_name](#output\_db\_instance\_name) | The database name | 64 | | [db\_instance\_port](#output\_db\_instance\_port) | The database port | 65 | 66 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/rds/demo/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | username = "root" 3 | db_name = "demo" 4 | db_instance_identifier = "${var.deployment_prefix}-demo-myrds" 5 | } 6 | 7 | ################################################################################ 8 | # SecretsManager Secret 9 | ################################################################################ 10 | 11 | resource "random_password" "master_password" { 12 | length = 32 13 | min_lower = 1 14 | min_numeric = 3 15 | min_special = 3 16 | min_upper = 3 17 | special = true 18 | numeric = true 19 | upper = true 20 | override_special = "!#$%&*()-_=+[]{}<>:?" 21 | } 22 | 23 | resource "aws_secretsmanager_secret" "demo" { 24 | name = "${var.deployment_prefix}-demo-myrds-db" 25 | description = "Demo credentials like Database password etc. for ${var.deployment_prefix} environment." 26 | kms_key_id = var.kms_key_id 27 | tags = { 28 | "Name" = "${var.deployment_prefix}-demo-myrds-db" 29 | "Type" = "Secrets Manager" 30 | } 31 | } 32 | 33 | resource "aws_secretsmanager_secret_version" "demo" { 34 | secret_id = aws_secretsmanager_secret.demo.id 35 | secret_string = jsonencode({ 36 | MYSQL_USER = local.username 37 | MYSQL_PASSWORD = random_password.master_password.result 38 | MYSQL_DATABASE = local.db_name 39 | MYSQL_HOST = module.demo.db_instance_address 40 | MYSQL_PORT = module.demo.db_instance_port 41 | SUPER_SECRET = var.my_password 42 | }) 43 | } 44 | 45 | ################################################################################ 46 | # Security Group 47 | ################################################################################ 48 | 49 | resource "aws_security_group" "demo" { 50 | name_prefix = "${var.deployment_prefix}-demo-rds-sg" 51 | description = "What does this rule enable" 52 | vpc_id = var.vpc_id 53 | tags = { 54 | Name = "${var.deployment_prefix}-demo-rds-sg" 55 | } 56 | } 57 | 58 | resource "aws_security_group_rule" "access_ingress_from_kubernetes_nodes" { 59 | type = "ingress" 60 | description = "Inbound traffic only from Kubernetes nodes" 61 | from_port = 3306 62 | to_port = 3306 63 | protocol = "tcp" 64 | source_security_group_id = var.all_worker_node_groups_sg_id 65 | security_group_id = aws_security_group.demo.id 66 | } 67 | 68 | 69 | resource "aws_security_group_rule" "extra_inbound_access" { 70 | count = var.add_extra_cidr_blocks ? 1 : 0 71 | type = "ingress" 72 | description = "Allow inbound access for additional CIDR blocks" 73 | from_port = 3306 74 | to_port = 3306 75 | protocol = "tcp" 76 | cidr_blocks = var.extra_cidr_blocks 77 | security_group_id = aws_security_group.demo.id 78 | } 79 | 80 | ################################################################################ 81 | # RDS Module 82 | ################################################################################ 83 | 84 | module "demo" { 85 | source = "terraform-aws-modules/rds/aws" 86 | version = "5.9.0" 87 | 88 | identifier = local.db_instance_identifier 89 | 90 | # All available versions: http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.VersionMgmt 91 | engine = var.engine 92 | engine_version = var.engine_version 93 | family = var.family 94 | major_engine_version = var.major_engine_version 95 | instance_class = var.instance_class 96 | performance_insights_enabled = var.performance_insights_enabled 97 | 98 | storage_type = "gp3" 99 | allocated_storage = var.allocated_storage 100 | max_allocated_storage = var.max_allocated_storage 101 | storage_encrypted = true 102 | kms_key_id = var.kms_key_id 103 | 104 | db_name = local.db_name 105 | username = local.username 106 | create_random_password = false 107 | password = random_password.master_password.result 108 | port = 3306 109 | 110 | multi_az = var.multi_az 111 | publicly_accessible = false 112 | db_subnet_group_name = var.database_subnet_group 113 | vpc_security_group_ids = [aws_security_group.demo.id] 114 | 115 | skip_final_snapshot = false 116 | final_snapshot_identifier_prefix = "${local.db_instance_identifier}-final" 117 | 118 | auto_minor_version_upgrade = true 119 | maintenance_window = "Mon:00:00-Mon:03:00" 120 | backup_retention_period = 7 121 | backup_window = "03:00-06:00" 122 | 123 | copy_tags_to_snapshot = true 124 | deletion_protection = var.deletion_protection 125 | create_db_option_group = false 126 | create_db_parameter_group = true 127 | 128 | parameters = [ 129 | { 130 | name = "require_secure_transport" 131 | value = "1" 132 | } 133 | ] 134 | 135 | tags = { 136 | Name = local.db_instance_identifier 137 | Type = "Relational Database Service" 138 | Engine = "MySQL" 139 | Dummy = "Tag_2" 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/rds/demo/outputs.tf: -------------------------------------------------------------------------------- 1 | output "db_instance_address" { 2 | description = "The address of the RDS instance" 3 | value = module.demo.db_instance_address 4 | } 5 | 6 | output "db_instance_name" { 7 | description = "The database name" 8 | value = module.demo.db_instance_name 9 | } 10 | 11 | output "db_instance_port" { 12 | description = "The database port" 13 | value = module.demo.db_instance_port 14 | } 15 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/rds/demo/variables.tf: -------------------------------------------------------------------------------- 1 | variable "deployment_prefix" { 2 | description = "Prefix of the deployment" 3 | type = string 4 | } 5 | 6 | variable "vpc_id" { 7 | type = string 8 | description = "The VPC ID where DB cluster should be deployed" 9 | } 10 | 11 | variable "add_extra_cidr_blocks" { 12 | description = "Controls if extra CIDR blocks should be added." 13 | type = bool 14 | default = false 15 | } 16 | 17 | variable "extra_cidr_blocks" { 18 | type = list(string) 19 | description = "Extra CIDR blocks to get access to database." 20 | default = [] 21 | } 22 | 23 | variable "all_worker_node_groups_sg_id" { 24 | type = string 25 | description = "The common SG ID of K8s nodes" 26 | } 27 | 28 | variable "database_subnet_group" { 29 | type = string 30 | description = "ID of database subnet group" 31 | } 32 | 33 | variable "engine" { 34 | description = "The database engine to use" 35 | type = string 36 | } 37 | 38 | variable "engine_version" { 39 | description = "The engine version to use" 40 | type = string 41 | } 42 | 43 | variable "family" { 44 | description = "The family of the DB parameter group" 45 | type = string 46 | } 47 | 48 | variable "major_engine_version" { 49 | description = "Specifies the major version of the engine that this option group should be associated with" 50 | type = string 51 | } 52 | 53 | variable "instance_class" { 54 | description = "The instance type of the RDS instance" 55 | type = string 56 | } 57 | 58 | variable "allocated_storage" { 59 | description = "The allocated storage in gigabytes" 60 | type = string 61 | } 62 | 63 | variable "max_allocated_storage" { 64 | description = "Specifies the value for Storage Autoscaling" 65 | type = number 66 | } 67 | 68 | variable "kms_key_id" { 69 | description = "The ARN for the KMS encryption key" 70 | type = string 71 | } 72 | 73 | variable "multi_az" { 74 | description = "Specifies if the RDS instance is multi-AZ" 75 | type = bool 76 | default = false 77 | } 78 | 79 | variable "deletion_protection" { 80 | description = "The database can't be deleted when this value is set to true" 81 | type = bool 82 | default = true 83 | } 84 | 85 | variable "performance_insights_enabled" { 86 | description = "Specifies whether Performance Insights are enabled" 87 | type = bool 88 | default = false 89 | } 90 | 91 | variable "my_password" { 92 | description = "My password" 93 | type = string 94 | sensitive = true 95 | } 96 | -------------------------------------------------------------------------------- /lesson-6-7-8/terraform-modules/modules/rds/demo/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.2" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.6" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = ">= 3.1" 12 | } 13 | } 14 | } 15 | --------------------------------------------------------------------------------