Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adding sprinkler ami pipeline #18

Merged
merged 1 commit into from
Jan 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions teams/sprinkler/backend.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Backend
terraform {
# `backend` blocks do not support variables, so the following are hard-coded here:
# - S3 bucket name, which is created in modernisation-platform-account/s3.tf
backend "s3" {
acl = "bucket-owner-full-control"
bucket = "modernisation-platform-terraform-state"
encrypt = true
key = "imagebuilder-sprinkler.tfstate" # replace team1 with your team name when copying this file
region = "eu-west-2"
workspace_key_prefix = "environments/accounts/core-shared-services" # This will store the object as environments/core-shared-services/${workspace}/imagebuilder-[team name].tfstate
}
}
5 changes: 5 additions & 0 deletions teams/sprinkler/base_variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
variable "networking" {

type = list(any)

}
35 changes: 35 additions & 0 deletions teams/sprinkler/components/rhel7/rhel7.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: Rhel7 example
description: Example Rhel7 component.
schemaVersion: 1.0
parameters:
- Version:
type: string
default: "1.0.1"
description: Component version (update this each time the file changes)
- Platform:
type: string
default: "Linux"
description: Platform.
phases:
- name: build
steps:
- name: HelloWorldStep
action: ExecuteBash
inputs:
commands:
- echo 'Hello World from the build phase.'
- name: validate
steps:
- name: HelloWorldStep
action: ExecuteBash
inputs:
commands:
- echo 'Hello World from the validate phase.'
- name: test
steps:
- name: HelloWorldStep
action: ExecuteBash
inputs:
commands:
- echo 'Hello world from the test phase'
4 changes: 4 additions & 0 deletions teams/sprinkler/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Retrieve KMS key for AMI/snapshot encryption
data "aws_kms_key" "sprinkler_ebs_encryption_key" {
key_id = "arn:aws:kms:eu-west-2:${local.environment_management.account_ids["sprinkler-development"]}:alias/sprinkler_ebs-encryption-key"
}
39 changes: 39 additions & 0 deletions teams/sprinkler/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
data "aws_organizations_organization" "root_account" {}
data "aws_caller_identity" "current" {}

locals {

team_name = "sprinkler"

root_account = data.aws_organizations_organization.root_account
application_name = "core-shared-services"
environment_management = jsondecode(data.aws_secretsmanager_secret_version.environment_management.secret_string)

environment = trimprefix(terraform.workspace, "${var.networking[0].application}-")
provider_name = "core-vpc-development"

# This takes the name of the Terraform workspace (e.g. core-vpc-production), strips out the application name (e.g. core-vpc), and checks if
# the string leftover is `-production`, if it isn't (e.g. core-vpc-non-production => -non-production) then it sets the var to false.
is-production = substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-production"
is-preproduction = substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-preproduction"
is_live = [substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-production" || substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-preproduction" ? "live" : "non-live"]

tags = {
business-unit = "Platforms"
application = "Modernisation Platform: ${terraform.workspace}"
is-production = local.is-production
owner = "Modernisation Platform: modernisation-platform@digital.justice.gov.uk"
}

json_data = jsondecode(file("networking.auto.tfvars.json"))

root_users_with_state_access = [
"arn:aws:iam::${local.root_account.master_account_id}:user/ModernisationPlatformOrganisationManagement",
"arn:aws:iam::${local.root_account.master_account_id}:user/DavidElliott"
]

ami_share_accounts = [
"${local.environment_management.account_ids["sprinkler-development"]}"
]

}
10 changes: 10 additions & 0 deletions teams/sprinkler/networking.auto.tfvars.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"networking": [
{
"business-unit": "",
"set": "",
"application": "core-shared-services"
}
]
}

18 changes: 18 additions & 0 deletions teams/sprinkler/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# AWS provider for the workspace you're working in (every resource will default to using this, unless otherwise specified)
provider "aws" {
region = "eu-west-2"
assume_role {
role_arn = "arn:aws:iam::${local.environment_management.account_ids[terraform.workspace]}:role/ModernisationPlatformAccess"
}
}

# AWS provider for the Modernisation Platform, to get things from there if required
provider "aws" {
alias = "modernisation-platform"
region = "eu-west-2"
}

provider "aws" {
alias = "bucket-replication"
region = "eu-west-1"
}
17 changes: 17 additions & 0 deletions teams/sprinkler/remote_states.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
data "terraform_remote_state" "modernisation-platform-repo" {
backend = "s3"
config = {
bucket = "modernisation-platform-terraform-state"
key = "environments/accounts/core-shared-services/core-shared-services-production/terraform.tfstate"
region = "eu-west-2"
}
}

data "terraform_remote_state" "mp-imagebuilder" {
backend = "s3"
config = {
bucket = "modernisation-platform-terraform-state"
key = "environments/accounts/core-shared-services/core-shared-services-production/imagebuilder-mp.tfstate"
region = "eu-west-2"
}
}
110 changes: 110 additions & 0 deletions teams/sprinkler/rhel7_pipeline.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
resource "aws_imagebuilder_image_pipeline" "rhel7" {
image_recipe_arn = aws_imagebuilder_image_recipe.rhel7.arn
infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.rhel7.arn
distribution_configuration_arn = aws_imagebuilder_distribution_configuration.rhel7.arn
name = local.rhel_pipeline.pipeline.name

schedule {
schedule_expression = local.rhel_pipeline.pipeline.schedule
pipeline_execution_start_condition = "EXPRESSION_MATCH_AND_DEPENDENCY_UPDATES_AVAILABLE"
}

depends_on = [
aws_imagebuilder_image_recipe.rhel7
]
}


/* This is being commented for reference, it is not necessary to deploy this and it takes a long time to apply.
resource "aws_imagebuilder_image" "rhel7" {
distribution_configuration_arn = aws_imagebuilder_distribution_configuration.rhel7.arn
image_recipe_arn = aws_imagebuilder_image_recipe.rhel7.arn
infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.rhel7.arn
}
*/


resource "aws_imagebuilder_image_recipe" "rhel7" {
block_device_mapping {
device_name = local.rhel_pipeline.recipe.device_name

ebs {
delete_on_termination = local.rhel_pipeline.recipe.ebs.delete_on_termination
volume_size = local.rhel_pipeline.recipe.ebs.volume_size
volume_type = local.rhel_pipeline.recipe.ebs.volume_type
encrypted = local.rhel_pipeline.recipe.ebs.encrypted
kms_key_id = data.aws_kms_key.sprinkler_ebs_encryption_key.arn
}
}

dynamic "component" {
for_each = toset(local.rhel_pipeline.components)
content {
component_arn = aws_imagebuilder_component.rhel7_components[component.key].arn
}
}

dynamic "component" {
for_each = toset(local.rhel_pipeline.aws_components)
content {
component_arn = "arn:aws:imagebuilder:eu-west-2:aws:component/${component.key}/x.x.x"
}
}

lifecycle {
create_before_destroy = true
}

name = local.rhel_pipeline.recipe.name
parent_image = local.rhel_pipeline.recipe.parent_image
version = local.rhel_pipeline.recipe.version
}


resource "aws_imagebuilder_infrastructure_configuration" "rhel7" {
description = local.rhel_pipeline.infra_config.description
instance_profile_name = data.terraform_remote_state.mp-imagebuilder.outputs.image_builder_profile
instance_types = local.rhel_pipeline.infra_config.instance_types
name = local.rhel_pipeline.infra_config.name
security_group_ids = local.rhel_pipeline.infra_config.security_group_ids
subnet_id = local.rhel_pipeline.infra_config.subnet_id
terminate_instance_on_failure = local.rhel_pipeline.infra_config.terminate_on_fail

logging {
s3_logs {
s3_bucket_name = data.terraform_remote_state.modernisation-platform-repo.outputs.imagebuilder_log_bucket_id
s3_key_prefix = local.team_name
}
}
}

// create each component in team directory
resource "aws_imagebuilder_component" "rhel7_components" {
for_each = { for file in local.rhel_pipeline.components : file => yamldecode(file("components/rhel7/${file}")) }

data = file("components/rhel7/${each.key}")
name = join("_", ["sprinkler", trimsuffix(each.key, ".yml")])
platform = yamldecode(file("components/rhel7/${each.key}")).parameters[1].Platform.default
version = yamldecode(file("components/rhel7/${each.key}")).parameters[0].Version.default

lifecycle {
create_before_destroy = true
}
}

resource "aws_imagebuilder_distribution_configuration" "rhel7" {
name = local.rhel_pipeline.distribution.name

distribution {
region = local.rhel_pipeline.distribution.region

ami_distribution_configuration {

name = local.rhel_pipeline.distribution.ami_name

launch_permission {
user_ids = local.ami_share_accounts
}
}
}
}
48 changes: 48 additions & 0 deletions teams/sprinkler/rhel7_pipeline_vars.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
locals {

rhel_pipeline = {

pipeline = {
name = join("", [local.team_name, "_rhel7"])
schedule = "cron(0 0 * * ? *)"
}

recipe = {
name = join("", [local.team_name, "_rhel7"])
parent_image = "arn:aws:imagebuilder:eu-west-2:${data.aws_caller_identity.current.account_id}:image/mp-rhel7/x.x.x"
version = "1.0.1"
device_name = "/dev/sda1"

ebs = {
delete_on_termination = true
volume_size = 30
volume_type = "gp2"
encrypted = true
}
}

infra_config = {
description = "Description here"
instance_types = ["t3.medium"]
name = join("", [local.team_name, "_rhel7"])
security_group_ids = [data.terraform_remote_state.modernisation-platform-repo.outputs.image_builder_security_group_id]
subnet_id = "${data.terraform_remote_state.modernisation-platform-repo.outputs.non_live_private_subnet_ids[0]}"
terminate_on_fail = true
}

distribution = {
name = join("", [local.team_name, "_rhel7"])
region = "eu-west-2"
ami_name = join("", [local.team_name, "_rhel7_{{ imagebuilder:buildDate }}"])
}

components = [
"rhel7.yml"
]

aws_components = [
"apache-tomcat-9-linux"
]
}

}
11 changes: 11 additions & 0 deletions teams/sprinkler/secrets.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Get secret by name for environment management
data "aws_secretsmanager_secret" "environment_management" {
provider = aws.modernisation-platform
name = "environment_management"
}

# Get latest secret value with ID from above. This secret stores account IDs for the Modernisation Platform sub-accounts
data "aws_secretsmanager_secret_version" "environment_management" {
provider = aws.modernisation-platform
secret_id = data.aws_secretsmanager_secret.environment_management.id
}