├── .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 |
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 |
--------------------------------------------------------------------------------