Skip to content

Commit 4ce1c30

Browse files
Scott WinklerScott Winkler
authored andcommitted
add chapter 11 code
1 parent 50143f6 commit 4ce1c30

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+364
-3274933
lines changed

chapter11/complete/main.tf

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
variable "aws" {
2+
type = object({ access_key = string, secret_key = string, region = string })
3+
}
4+
5+
variable "vcs_repo" {
6+
type = object({ identifier = string, branch = string, oauth_token = string })
7+
}
8+
9+
provider "aws" {
10+
access_key = var.aws.access_key
11+
secret_key = var.aws.secret_key
12+
region = var.aws.region
13+
}
14+
15+
module "s3backend" {
16+
source = "scottwinkler/s3backend/aws"
17+
}
18+
19+
module "codepipeline" {
20+
source = "./modules/codepipeline"
21+
name = "terraform-in-action"
22+
vcs_repo = var.vcs_repo
23+
auto_apply = true
24+
environment = {
25+
AWS_ACCESS_KEY_ID = var.aws.access_key
26+
AWS_SECRET_ACCESS_KEY = var.aws.secret_key
27+
CONFIRM_DESTROY = 1
28+
}
29+
s3_backend_config = module.s3backend.config
30+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
resource "aws_iam_role" "codebuild_role" {
2+
name = "${local.namespace}-codebuild"
3+
assume_role_policy = <<-EOF
4+
{
5+
"Version": "2012-10-17",
6+
"Statement": [
7+
{
8+
"Effect": "Allow",
9+
"Principal": {
10+
"Service": "codebuild.amazonaws.com"
11+
},
12+
"Action": "sts:AssumeRole"
13+
}
14+
]
15+
}
16+
EOF
17+
}
18+
19+
resource "aws_iam_role_policy" "codebuild_policy" {
20+
role = aws_iam_role.codebuild_role.name
21+
policy = <<-EOF
22+
{
23+
"Version": "2012-10-17",
24+
"Statement": [
25+
{
26+
"Effect": "Allow",
27+
"Resource": [
28+
"*"
29+
],
30+
"Action": [
31+
"logs:CreateLogGroup",
32+
"logs:CreateLogStream",
33+
"logs:PutLogEvents"
34+
]
35+
},
36+
{
37+
"Effect":"Allow",
38+
"Action": [
39+
"s3:GetObject",
40+
"s3:GetObjectVersion",
41+
"s3:GetBucketVersioning",
42+
"s3:PutObject"
43+
],
44+
"Resource": [
45+
"${aws_s3_bucket.codepipeline_bucket.arn}",
46+
"${aws_s3_bucket.codepipeline_bucket.arn}/*"
47+
]
48+
}
49+
]
50+
}
51+
EOF
52+
}
53+
54+
resource "aws_iam_role" "codepipeline_role" {
55+
name = "${local.namespace}-pipeline-role"
56+
assume_role_policy = <<-EOF
57+
{
58+
"Version": "2012-10-17",
59+
"Statement": [
60+
{
61+
"Effect": "Allow",
62+
"Principal": {
63+
"Service": "codepipeline.amazonaws.com"
64+
},
65+
"Action": "sts:AssumeRole"
66+
}
67+
]
68+
}
69+
EOF
70+
}
71+
72+
resource "aws_iam_role_policy" "codepipeline_policy" {
73+
name = "codepipeline_policy"
74+
role = aws_iam_role.codepipeline_role.id
75+
76+
policy = <<-EOF
77+
{
78+
"Version": "2012-10-17",
79+
"Statement": [
80+
{
81+
"Effect":"Allow",
82+
"Action": [
83+
"s3:GetObject",
84+
"s3:GetObjectVersion",
85+
"s3:GetBucketVersioning",
86+
"s3:PutObject"
87+
],
88+
"Resource": [
89+
"${aws_s3_bucket.codepipeline_bucket.arn}",
90+
"${aws_s3_bucket.codepipeline_bucket.arn}/*"
91+
]
92+
},
93+
{
94+
"Effect": "Allow",
95+
"Action": [
96+
"sns:Publish"
97+
],
98+
"Resource": "${aws_sns_topic.codepipeline.arn}"
99+
},
100+
{
101+
"Effect": "Allow",
102+
"Action": [
103+
"codebuild:BatchGetBuilds",
104+
"codebuild:StartBuild"
105+
],
106+
"Resource": "*"
107+
}
108+
]
109+
}
110+
EOF
111+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
resource "random_string" "rand" {
2+
length = 24
3+
special = false
4+
upper = false
5+
}
6+
7+
locals {
8+
namespace = substr(join("-", [var.name, random_string.rand.result]), 0, 24)
9+
projects = ["plan", "apply"]
10+
}
11+
12+
resource "aws_codebuild_project" "project" {
13+
count = length(local.projects)
14+
name = "${local.namespace}-${local.projects[count.index]}"
15+
service_role = aws_iam_role.codebuild_role.id
16+
17+
artifacts {
18+
type = "NO_ARTIFACTS"
19+
}
20+
21+
environment {
22+
compute_type = "BUILD_GENERAL1_SMALL"
23+
image = "hashicorp/terraform:${var.terraform_version}"
24+
type = "LINUX_CONTAINER"
25+
}
26+
27+
source {
28+
type = "NO_SOURCE"
29+
buildspec = file("${path.module}/templates/buildspec_${local.projects[count.index]}.yml")
30+
}
31+
}
32+
33+
locals {
34+
backend = templatefile("${path.module}/templates/backend.json", { config : var.s3_backend_config, name : local.namespace })
35+
default_environment = {
36+
TF_IN_AUTOMATION = "1"
37+
TF_INPUT = "1"
38+
CONFIRM_DESTROY = "0"
39+
WORKING_DIRECTORY = var.working_directory
40+
BACKEND = local.backend,
41+
}
42+
environment = jsonencode([for k, v in merge(local.default_environment, var.environment) : { name : k, value : v, type : "PLAINTEXT" }])
43+
}
44+
45+
resource "aws_s3_bucket" "codepipeline_bucket" {
46+
bucket = "${local.namespace}-codepipeline-bucket"
47+
acl = "private"
48+
force_destroy = true
49+
}
50+
51+
resource "aws_sns_topic" "codepipeline" {
52+
name = "${local.namespace}-pipeline-topic"
53+
}
54+
55+
resource "aws_codepipeline" "codepipeline" {
56+
name = "${local.namespace}-pipeline"
57+
role_arn = aws_iam_role.codepipeline_role.arn
58+
59+
artifact_store {
60+
location = aws_s3_bucket.codepipeline_bucket.bucket
61+
type = "S3"
62+
}
63+
64+
stage {
65+
name = "Source"
66+
67+
action {
68+
name = "Source"
69+
category = "Source"
70+
owner = "ThirdParty"
71+
provider = "GitHub"
72+
version = "1"
73+
output_artifacts = ["source_output"]
74+
75+
configuration = {
76+
Owner = split("/", var.vcs_repo.identifier)[0]
77+
Repo = split("/", var.vcs_repo.identifier)[1]
78+
Branch = var.vcs_repo.branch
79+
OAuthToken = var.vcs_repo.oauth_token
80+
}
81+
}
82+
}
83+
84+
stage {
85+
name = "Plan"
86+
87+
action {
88+
name = "Plan"
89+
category = "Build"
90+
owner = "AWS"
91+
provider = "CodeBuild"
92+
input_artifacts = ["source_output"]
93+
version = "1"
94+
95+
configuration = {
96+
ProjectName = aws_codebuild_project.project[0].name
97+
EnvironmentVariables = local.environment
98+
}
99+
}
100+
}
101+
102+
dynamic "stage" {
103+
for_each = ! var.auto_apply ? [1] : []
104+
content {
105+
name = "Approve"
106+
107+
action {
108+
name = "Approve"
109+
category = "Approval"
110+
owner = "AWS"
111+
provider = "Manual"
112+
version = "1"
113+
114+
configuration = {
115+
CustomData = "Please review output of plan and approve"
116+
NotificationArn = aws_sns_topic.codepipeline.arn
117+
}
118+
}
119+
}
120+
}
121+
122+
stage {
123+
name = "Apply"
124+
125+
action {
126+
name = "Apply"
127+
category = "Build"
128+
owner = "AWS"
129+
provider = "CodeBuild"
130+
input_artifacts = ["source_output"]
131+
version = "1"
132+
133+
configuration = {
134+
ProjectName = aws_codebuild_project.project[1].name
135+
EnvironmentVariables = local.environment
136+
}
137+
}
138+
}
139+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"terraform": {
3+
"backend": {
4+
"s3": {
5+
"bucket": "${config.bucket}",
6+
"key": "aws/${name}",
7+
"region": "${config.region}",
8+
"encrypt": true,
9+
"role_arn": "${config.role_arn}",
10+
"dynamodb_table": "${config.dynamodb_table}"
11+
}
12+
}
13+
}
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: 0.2
2+
phases:
3+
build:
4+
commands:
5+
- cd $WORKING_DIRECTORY
6+
- echo $BACKEND >> backend.tf.json
7+
- terraform init
8+
- |
9+
if [[ "$CONFIRM_DESTROY" == "0" ]]; then
10+
terraform apply -auto-approve
11+
else
12+
terraform destroy -auto-approve
13+
fi
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: 0.2
2+
phases:
3+
build:
4+
commands:
5+
- cd $WORKING_DIRECTORY
6+
- echo $BACKEND >> backend.tf.json
7+
- terraform init
8+
- |
9+
if [[ "$CONFIRM_DESTROY" == "0" ]]; then
10+
terraform plan
11+
else
12+
terraform plan -destroy
13+
fi
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
variable "name" {
2+
type = string
3+
default = "terraform"
4+
description = "A project name to use for resource mapping"
5+
}
6+
7+
variable "auto_apply" {
8+
type = bool
9+
default = false
10+
description = "Whether to automatically apply changes when a Terraform plan is successful. Defaults to false."
11+
}
12+
13+
variable "terraform_version" {
14+
type = string
15+
default = "latest"
16+
description = "The version of Terraform to use for this workspace. Defaults to the latest available version."
17+
}
18+
19+
variable "working_directory" {
20+
type = string
21+
default = "."
22+
description = "A relative path that Terraform will execute within. Defaults to the root of your repository."
23+
}
24+
25+
variable "vcs_repo" {
26+
type = object({ identifier = string, branch = string, oauth_token = string })
27+
description = "Settings for the workspace's VCS repository."
28+
}
29+
30+
variable "environment" {
31+
type = map(string)
32+
default = {}
33+
description = "A map of environment varaibles to use for this workspace"
34+
}
35+
36+
variable "s3_backend_config" {
37+
type = object({
38+
bucket = string,
39+
region = string,
40+
role_arn = string,
41+
dynamodb_table = string,
42+
})
43+
description = "Settings for configuring the S3 remote backend"
44+
}

chapter8/misc/browserquest/.dockerignore

Lines changed: 0 additions & 2 deletions
This file was deleted.

chapter8/misc/browserquest/.gitignore

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)