ImageBuilder and Terraform - Handy Hints

This is for my benefit as much as anybody else, because it took me a while to figure things out:

Most of the time when you write for AWS ImageBuilder, the docs tell you to create separate YAML files containing your components.  That's fine, but what if you want to do dynamic substitutions on path and file names?  In that case you probably want to do the definition in the HCL language.  That is, within the actual Terraform code itself.

Using S3

One of the more fiddly bits is pulling things from S3 to install on your new instance.  You need to do two things:

  • Have an IAM policy which allows access; and
  • Write the component to do the job

Writing the IAM

Create a policy resource that looks something like this:

resource "aws_iam_policy" "s3_policy" {
    name = "s3-policy"
    policy = jsonencode(
      {
          Version = "2012-10-17"
          Statement = [
            {
              Effect = "Allow"
              Action = [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:GetObjectAttributes"
              ]
              Resource = [
                "arn:aws:s3:::${var.code_bucket}"
              ]
            }
          ]
      }
    )
}
This is of course, the bare minimum but it gets the job done.  Now reference this from your role:

resource "aws_iam_role_policy_attachment" "attach" {
    role = aws_iam_role.role.name
    policy_arn = aws_iam_policy.s3_policy.arn
}

And pull stuff from S3

This is a little more complex example, but you're probably going to want to unpack the file, make it executable, etc:

resource "aws_imagebuilder_component" "load_code" {
  data = yamlencode(
    {
        phases = [
            {
                name = "build"
                steps = [
                    {
                        action = "S3Download"
                        inputs = [{
                            source = "s3://${var.code_bucket}/${var.code_file}"
                            destination = "/tmp/${var.code_file}"
                        }]
                        maxAttempts = 3
                        name      = "Copy_Code"
                        onFailure = "Abort"
                    },
                    {
                        action = "ExecuteBash"
                        inputs = {
                            commands = [
                                "cd /opt",
                                "sudo mkdir -p /opt/app",
                                "sudo tar -xvf /tmp/${var.code_file} -C /opt/app"
                                ]
                        }
                        name      = "Install_App"
                        onFailure = "Abort"
                    },
                    {
                        action = "ExecuteBash"
                        inputs = {
                            commands = [
                                "cd /opt/app",
                                "chmod +x ./run.sh"
                                ]
                        }
                        name      = "Configure_App"
                        onFailure = "Continue"
                    }

                ]
            }
        ]
        schemaVersion = 1.0
    }
    )
    name     = "App-Deploy"
    platform = "Linux"
    version  = "1.0.0"
}

Enjoy!



Comments

Popular posts from this blog

The QYT KT-7900D

Recording weather with Arduino, Elasticsearch and Kibana

Exploring Solar Power - Let there be smoke!