AWS Launch Template : Not MIME error

I am trying to setup a batch compute environment following these tutorial

From JosephMin and Template MIME Handling

My main.tf looks like this

# https://medium.com/swlh/terraform-aws-batch-and-aws-efs-8682c112d742

# │  135:           "${aws_s3_bucket.results_s3.arn}",
variable "s3_arn" {
  type = string
}

variable "ecr_repository_url" {
  type = string
}


provider "aws" {
  region = "ca-central-1"
}

# Security Setup
# Retrieves the default vpc for this region
data "aws_vpc" "default" {
  default = true
}
# Retrieves the subnet ids in the default vpc
data "aws_subnet_ids" "all_default_subnets" {
  vpc_id = data.aws_vpc.default.id
}


# IAM Role for batch processing
resource "aws_iam_role" "batch_role" {
  name               = "batch_role"
  assume_role_policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement":
    [
      {
          "Action": "sts:AssumeRole",
          "Effect": "Allow",
          "Principal": {
            "Service": "batch.amazonaws.com"
          }
      }
    ]
}
EOF
tags = {
    created-by = "terraform"
  }
}
# Attach the Batch policy to the Batch role
resource "aws_iam_role_policy_attachment" "policy_attachment" {
  role       = aws_iam_role.batch_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBatchServiceRole"
}
# Security Group for batch processing
resource "aws_security_group" "batch_security_group" {
  name        = "batch_security_group"
  description = "AWS Batch Security Group for batch jobs"
  vpc_id      = data.aws_vpc.default.id
egress {
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
tags = {
    created-by = "terraform"
  }
}



# IAM Role for underlying EC2 instances
resource "aws_iam_role" "ec2_role" {
  name = "ec2_role"
assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
tags = {
    created-by = "terraform"
  }
}
# Assign the EC2 role to the EC2 profile
resource "aws_iam_instance_profile" "ec2_profile" {
  name = "ec2_profile"
  role = aws_iam_role.ec2_role.name
}
# Attach the EC2 container service policy to the EC2 role
resource "aws_iam_role_policy_attachment" "ec2_policy_attachment" {
  role       = aws_iam_role.ec2_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
}



# IAM Role for jobs
resource "aws_iam_role" "job_role" {
  name               = "job_role"
  assume_role_policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement":
    [
      {
          "Action": "sts:AssumeRole",
          "Effect": "Allow",
          "Principal": {
            "Service": "ecs-tasks.amazonaws.com"
          }
      }
    ]
}
EOF
tags = {
    created-by = "terraform"
  }
}
# S3 read/write policy
resource "aws_iam_policy" "s3_policy" {
  name   = "s3_policy"
  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
        "Effect": "Allow",
        "Action": [
            "s3:Get*",
            "s3:List*",
            "s3:Put*"
        ],
        "Resource": [
          "${var.s3_arn}",
          "${var.s3_arn}/*"
        ]
    }
  ]
}
EOF
}

# Attach the policy to the job role
resource "aws_iam_role_policy_attachment" "job_policy_attachment" {
  role       = aws_iam_role.job_role.name
  policy_arn = aws_iam_policy.s3_policy.arn
}



resource "aws_security_group" "efs_security_group" {
  name        = "efs_security_group"
  description = "Allow NFS traffic."
  vpc_id      = data.aws_vpc.default.id
lifecycle {
    create_before_destroy = true
  }
ingress {
    from_port       = "2049"
    to_port         = "2049"
    protocol        = "tcp"
    security_groups = [aws_security_group.batch_security_group.id]
  }
egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
    description = "No Outbound Restrictions"
  }
}



# EFS for sharing protein databases
resource "aws_efs_file_system" "efs" {
  creation_token   = "efs"
  performance_mode = "generalPurpose"
  encrypted        = "true"
}
resource "aws_efs_mount_target" "efs_mount_target" {
  count          = length(data.aws_subnet_ids.all_default_subnets.ids)
  file_system_id = aws_efs_file_system.efs.id
  subnet_id      = element(tolist(data.aws_subnet_ids.all_default_subnets.ids), count.index)
  security_groups = [
    aws_security_group.efs_security_group.id,
    aws_security_group.batch_security_group.id
  ]
}

resource "aws_launch_template" "launch_template" {
  name = "launch_template"
  update_default_version = true
  user_data              = base64encode(data.template_file.efs_template_file.rendered)
}

data "template_file" "efs_template_file" {
  template = "${file("${path.module}/launch_template_user_data.tpl")}"
  vars = {
	efs_id        = aws_efs_file_system.efs.id
	efs_directory = "/mnt/efs"
  }
}


resource "aws_batch_compute_environment" "batch_environment" {
  compute_environment_name = "batch-environment2"
  compute_resources {
    instance_role = aws_iam_instance_profile.ec2_profile.arn
    launch_template {
      launch_template_id = aws_launch_template.launch_template.id
      version              = "$Latest"
    }
    instance_type = [
      "optimal"
    ]
    max_vcpus = 2
    min_vcpus = 0
    security_group_ids = [
      aws_security_group.batch_security_group.id,
      aws_security_group.efs_security_group.id
    ]
    subnets = data.aws_subnet_ids.all_default_subnets.ids
    type    = "EC2"
  }
  service_role = aws_iam_role.batch_role.arn
  type         = "MANAGED"
tags = {
    created-by = "terraform"
  }
}
resource "aws_batch_job_queue" "job_queue" {
  name     = "job_queue"
  state    = "ENABLED"
  priority = 1
  compute_environments = [
    aws_batch_compute_environment.batch_environment.arn
  ]
  depends_on = [aws_batch_compute_environment.batch_environment]
tags = {
    created-by = "terraform"
  }
}
resource "aws_batch_job_definition" "job" {
  name = "job"
  type = "container"
  parameters = {}
  container_properties = <<CONTAINER_PROPERTIES
{
  "image": "var.ecr_repository_url",
  "jobRoleArn": "${aws_iam_role.job_role.arn}",
  "vcpus": 2,
  "memory": 1024,
  "environment": [],
  "volumes": [
      {
          "host": {
              "sourcePath": "/mnt/efs"
          },
          "name": "efs"
      }
  ],
  "mountPoints": [
      {
          "containerPath": "/mnt/efs",
          "sourceVolume": "efs",
          "readOnly": false
      }
  ],
  "command": []
}
CONTAINER_PROPERTIES
tags = {
    created-by = "terraform"
  }
}

But I keep getting

Error: error waiting for Batch Compute Environment (batch-environment) disable: unexpected state 'INVALID', wanted target 'VALID'. last error: CLIENT_ERROR - Launch Template UserData is not MIME multipart format

My template file looks like this

MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==BOUNDARY=="

--==BOUNDARY==
Content-Type: text/cloud-boothook; charset="us-ascii"

#cloud-boothook
#!/bin/bash
cloud-init-per once docker_options echo 'OPTIONS="$${OPTIONS} --storage-opt dm.basesize=20G"' >> /etc/sysconfig/docker

--==BOUNDARY==
Content-Type: text/cloud-config; charset="us-ascii"

packages:
- amazon-efs-utils

runcmd:
- mkdir -p ${efs_directory}
- echo "${efs_id}:/ ${efs_directory} efs _netdev,tls,iam 0 0" >> /etc/fstab
- mount -a -t efs defaults

--==BOUNDARY==--

Any suggestions on where I have made mistakes ?

Cheers

1 Like

I keep getting the same with this config:

test
|---- main.tf
|---- user_data.sh

// main.tf

data "template_file" "user_data" {
  template = file("${path.module}/user_data.sh")
}

resource "aws_launch_template" "instance"{
....

user_data = base64encode(data.template_file.user_data.rendered)
}

where user_data.sh is simply:

#!/bin/bash
#
echo "Hello World!"

upd: I was able to workaround it with cloudinit data