gruntwork-io / terratest

Terratest is a Go library that makes it easier to write automated tests for your infrastructure code.
https://terratest.gruntwork.io/
Apache License 2.0
7.47k stars 1.32k forks source link

Add support for packer init with multiple .hcl files #1271

Open rhys96 opened 1 year ago

rhys96 commented 1 year ago

When the packer configuration is separated across multiple .hcl files, Terratest does not initialise packer when Template in the packer.Options is set to ".". To get Terratest to initialise packer, I have to set Template to the path of a .hcl file.

Is there an additional setting I am missing from my packer options? Or, is a modification to terratest required?

packerOptions := &packer.Options{
  Template: ".",

  WorkingDir: ".",
}
rhys96 commented 1 year ago

Example

Create the packer configuration.

/build.pkr.hcl

build {
  sources = [
    "source.amazon-ebs.ubuntu"
  ]

  provisioner "shell" {
    inline = [
      "cloud-init status --wait",
    ]
  }

  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y apache2",
      "echo \"<html><body><h1>Hello World!</h1></body></html>\" | sudo tee /var/www/html/index.html",
      "sudo systemctl restart apache2"
    ]
  }
}

/sources.pkr.hcl

locals {
  name = "ubuntu-${formatdate("YYYY-MM-DD-hh-mm", timestamp())}"
}

data "amazon-ami" "ubuntu" {
  most_recent = true

  filters = {
    name = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"
    virtualization-type = "hvm"
  }

  owners = ["099720109477"] # Canonical
}

source "amazon-ebs" "ubuntu" {
  ami_name                = "${local.name}"
  ami_description         = "Managed by Packer"
  ami_virtualization_type = "hvm"

  source_ami    = data.amazon-ami.ubuntu.id
  instance_type = "t3.micro"

  communicator = "ssh"
  ssh_username = "ubuntu"

  snapshot_tags = {
    Name = "${local.name}-snapshot"
  }

  tags = {
    "Name" = "${local.name}"
  }
}

Create a test file based on terraform_packer_example_test.go and make the following edit:

/packer_test.go

  // omitted...
  packerOptions := &packer.Options{
    Template: ".",

    WorkingDir: workingDir,
  }
  // omitted...

Then run terratest.

go test -v ./packer_test.go

<omitted output>
TestMultipleStagesExample 2023-04-22T15:33:15+01:00 logger.go:66: Running Packer to generate a custom artifact for template .
TestMultipleStagesExample 2023-04-22T15:33:15+01:00 logger.go:66: Creating a temporary directory for Packer plugins
TestMultipleStagesExample 2023-04-22T15:33:15+01:00 logger.go:66: Running command packer with args [-version]
TestMultipleStagesExample 2023-04-22T15:33:15+01:00 logger.go:66: 1.8.6
TestMultipleStagesExample 2023-04-22T15:33:16+01:00 logger.go:66: Skipping 'packer init' because it is only supported for HCL2 templates
<ommited output>

You can see in the console output that packer init is skipped because it states it is only supported for HCL2 templates.

Proposed Solution

If there isn't an option I've missed in the docs. I'd like to propose defaulting to initialising packer if Template is not provided in the Options. Instead, terratest would be configured to run against the working directory. For example:

 packerOptions := &packer.Options{
    WorkingDir: workingDir,
  }

I believe this solution would still be backwards compatible because a user could still provide an argument for Template, which could continue to have the same behaviour.