This follows #8232 which added the code to generate the code required to parse
HCL files for each packer component.
All old config files of packer will keep on working the same. Packer takes one
argument. When a directory is passed, all files in the folder with a name
ending with “.pkr.hcl” or “.pkr.json” will be parsed using the HCL2 format.
When a file ending with “.pkr.hcl” or “.pkr.json” is passed it will be parsed
using the HCL2 format. For every other case; the old packer style will be used.
## 1. the hcl2template pkg can create a packer.Build from a set of HCL (v2) files
I had to make the packer.coreBuild (which is our one and only packer.Build ) a public struct with public fields
## 2. Components interfaces get a new ConfigSpec Method to read a file from an HCL file.
This is a breaking change for packer plugins.
a packer component can be a: builder/provisioner/post-processor
each component interface now gets a `ConfigSpec() hcldec.ObjectSpec`
which allows packer to tell what is the layout of the hcl2 config meant
to configure that specific component.
This ObjectSpec is sent through the wire (RPC) and a cty.Value is now
sent through the already existing configuration entrypoints:
Provisioner.Prepare(raws ...interface{}) error
Builder.Prepare(raws ...interface{}) ([]string, error)
PostProcessor.Configure(raws ...interface{}) error
close#1768
Example hcl files:
```hcl
// file amazon-ebs-kms-key/run.pkr.hcl
build {
sources = [
"source.amazon-ebs.first",
]
provisioner "shell" {
inline = [
"sleep 5"
]
}
post-processor "shell-local" {
inline = [
"sleep 5"
]
}
}
// amazon-ebs-kms-key/source.pkr.hcl
source "amazon-ebs" "first" {
ami_name = "hcl2-test"
region = "us-east-1"
instance_type = "t2.micro"
kms_key_id = "c729958f-c6ba-44cd-ab39-35ab68ce0a6c"
encrypt_boot = true
source_ami_filter {
filters {
virtualization-type = "hvm"
name = "amzn-ami-hvm-????.??.?.????????-x86_64-gp2"
root-device-type = "ebs"
}
most_recent = true
owners = ["amazon"]
}
launch_block_device_mappings {
device_name = "/dev/xvda"
volume_size = 20
volume_type = "gp2"
delete_on_termination = "true"
}
launch_block_device_mappings {
device_name = "/dev/xvdf"
volume_size = 500
volume_type = "gp2"
delete_on_termination = true
encrypted = true
}
ami_regions = ["eu-central-1"]
run_tags {
Name = "packer-solr-something"
stack-name = "DevOps Tools"
}
communicator = "ssh"
ssh_pty = true
ssh_username = "ec2-user"
associate_public_ip_address = true
}
```
So that it works for all builders as some use it with the following field names: launch_block_device_mappings, ami_block_device_mappings or ebs_volumes. the refactored docs weird being to specific.
Subnet information is only really needed when the specified `vpc_id` is
not the default VPC for the region where the builder is being executed.
This change uses the AWS API to determine if the VPC provided is a
non-default VPC and only validates the existence of a `subnet_id` if a
user has provided a non-default `vpc_id`.
Tests after change
```
> make test TEST=./builder/amazon/... TESTARGS='-count=1 -v -run=TestStepPreValidate_checkVpc'
...
=== RUN TestStepPreValidate_checkVpc
=== RUN TestStepPreValidate_checkVpc/DefaultVpc
=== RUN TestStepPreValidate_checkVpc/NonDefaultVpcNoSubnet
=== RUN TestStepPreValidate_checkVpc/NonDefaultVpcWithSubnet
=== RUN TestStepPreValidate_checkVpc/SubnetWithNoVpc
=== RUN TestStepPreValidate_checkVpc/NoVpcInformation
--- PASS: TestStepPreValidate_checkVpc (0.00s)
--- PASS: TestStepPreValidate_checkVpc/DefaultVpc (0.00s)
--- PASS: TestStepPreValidate_checkVpc/NonDefaultVpcNoSubnet (0.00s)
--- PASS: TestStepPreValidate_checkVpc/NonDefaultVpcWithSubnet (0.00s)
--- PASS: TestStepPreValidate_checkVpc/SubnetWithNoVpc (0.00s)
--- PASS: TestStepPreValidate_checkVpc/NoVpcInformation (0.00s)
PASS
...
```
It is simply the best/simplest solution and trying to prevent users from passing and integer here would be like opening a can of worms. Because:
* we cannot make mapstructure validate our duration string ( with an UnmarshalJSON func etc.)
* we cannot make mapstructure spit a string instead of a duration and packer will decode-encode-decode config.
* the hcl2 generated code asks for a string, so this will be enforced by default.
Before this commit it was possible to set a duration using an integer or a float. Go's time.Duration is an int64 internally an mapstructure will take advantage of this and load the number as a int64 but `1` means one ns which is unexpected/confusing. To avoid confusion and enforce readability this forces users to pass a string with a unit for a duration; ex "56s".
* Allows `run_volume_tags` to be set without requiring a major rewrite
of the (common) amazon builder code used to start an instance.
The common start up code tags the instance and *all attached volumes
at creation*. If `run_volume_tags` are set this means that any volumes
specified in `ebs_volumes` will *initially* be tagged with the
`run_volume_tags` rather than the tags set in the `ebs_volumes`
section
* Once the instance is reported to be 'ready' the step to tag the EBS
volumes is run. Once complete all volumes should have the tags
requested by the user:
* Volumes associated with the source instance should be tagged with
the tags set in `run_volume_tags` (if any)
* Each EBS volumes specified in the `ebs_volumes` section of the
template should only be tagged with its associated tags (if any)
* Currently this results in *all* volumes attached to the instance
being tagged with the `run_volume_tags`. This includes any `ebs_volumes`
for which the user may have configured other tags.
* This issue will be addressed in a later commit
* add missing `temporary_key_pair_name` field for alicloud
* add missing description to `vpc_filter` for aws
* add missing ssh communicator fields for aws
* add links for aws
* update vmware-vmx docs
* manually describe AMI Configuration section for ebsvolume
* display missing required ami_name field for aws
* add missing fields for docker
* add missing fields for openstack
Without conflicting over the name of the launch template that they create/delete.
Previously, the launch template name was just hard coded to `packer-fleet-launch-template`, but since AWS enforces unique template names within an account, this caused simultaneously running packer instances to hit template-already-exists errors when creating their templates and race-conditions around deleting the template. Now, the template name is randomly generated on each run, so there should be no conflicts.