Add Amazon AMI data source to hcl_upgrade command (#10491)
This commit is contained in:
parent
4cb6e07900
commit
e44cb9d7e5
|
@ -7,6 +7,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
texttemplate "text/template"
|
texttemplate "text/template"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
"github.com/hashicorp/hcl/v2/hclwrite"
|
"github.com/hashicorp/hcl/v2/hclwrite"
|
||||||
"github.com/hashicorp/packer-plugin-sdk/template"
|
"github.com/hashicorp/packer-plugin-sdk/template"
|
||||||
hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
|
hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
@ -91,10 +93,14 @@ const (
|
||||||
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
|
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
|
||||||
build {
|
build {
|
||||||
`
|
`
|
||||||
|
amazonAmiDataHeader = `
|
||||||
|
# The amazon-ami data block is generated from your amazon builder source_ami_filter; a data
|
||||||
|
# from this block can be referenced in source and locals blocks.
|
||||||
|
# Read the documentation for data blocks here:
|
||||||
|
# https://www.packer.io/docs/templates/hcl_templates/blocks/data`
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2UpgradeArgs) int {
|
func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2UpgradeArgs) int {
|
||||||
|
|
||||||
out := &bytes.Buffer{}
|
out := &bytes.Buffer{}
|
||||||
var output io.Writer
|
var output io.Writer
|
||||||
if err := os.MkdirAll(filepath.Dir(cla.OutputFile), 0); err != nil {
|
if err := os.MkdirAll(filepath.Dir(cla.OutputFile), 0); err != nil {
|
||||||
|
@ -179,11 +185,16 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
|
||||||
for _, builder := range tpl.Builders {
|
for _, builder := range tpl.Builders {
|
||||||
builders = append(builders, builder)
|
builders = append(builders, builder)
|
||||||
}
|
}
|
||||||
sort.Slice(builders, func(i, j int) bool {
|
|
||||||
return builders[i].Type+builders[i].Name < builders[j].Type+builders[j].Name
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := c.writeAmazonAmiDatasource(builders, out); err != nil {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(builders, func(i, j int) bool {
|
||||||
|
return builders[i].Type+builders[i].Name < builders[j].Type+builders[j].Name
|
||||||
|
})
|
||||||
|
|
||||||
out.Write([]byte(sourcesHeader))
|
out.Write([]byte(sourcesHeader))
|
||||||
|
|
||||||
for i, builderCfg := range builders {
|
for i, builderCfg := range builders {
|
||||||
|
@ -287,6 +298,61 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *HCL2UpgradeCommand) writeAmazonAmiDatasource(builders []*template.Builder, out *bytes.Buffer) error {
|
||||||
|
amazonAmiFilters := []map[string]interface{}{}
|
||||||
|
first := true
|
||||||
|
i := 1
|
||||||
|
for _, builder := range builders {
|
||||||
|
if strings.HasPrefix(builder.Type, "amazon-") {
|
||||||
|
if sourceAmiFilter, ok := builder.Config["source_ami_filter"]; ok {
|
||||||
|
sourceAmiFilterCfg := map[string]interface{}{}
|
||||||
|
if err := mapstructure.Decode(sourceAmiFilter, &sourceAmiFilterCfg); err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Failed to write amazon-ami data source: %v", err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate := false
|
||||||
|
dataSourceName := fmt.Sprintf("autogenerated_%d", i)
|
||||||
|
for j, filter := range amazonAmiFilters {
|
||||||
|
if reflect.DeepEqual(filter, sourceAmiFilter) {
|
||||||
|
duplicate = true
|
||||||
|
dataSourceName = fmt.Sprintf("autogenerated_%d", j+1)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a hack...
|
||||||
|
// Use templating so that it could be correctly transformed later into a data resource
|
||||||
|
sourceAmiDataRef := fmt.Sprintf("{{ data `amazon-ami.%s.id` }}", dataSourceName)
|
||||||
|
|
||||||
|
if duplicate {
|
||||||
|
delete(builder.Config, "source_ami_filter")
|
||||||
|
builder.Config["source_ami"] = sourceAmiDataRef
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
amazonAmiFilters = append(amazonAmiFilters, sourceAmiFilterCfg)
|
||||||
|
delete(builder.Config, "source_ami_filter")
|
||||||
|
builder.Config["source_ami"] = sourceAmiDataRef
|
||||||
|
i++
|
||||||
|
|
||||||
|
if first {
|
||||||
|
out.Write([]byte(amazonAmiDataHeader))
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
datasourceContent := hclwrite.NewEmptyFile()
|
||||||
|
body := datasourceContent.Body()
|
||||||
|
body.AppendNewline()
|
||||||
|
sourceBody := body.AppendNewBlock("data", []string{"amazon-ami", dataSourceName}).Body()
|
||||||
|
jsonBodyToHCL2Body(sourceBody, sourceAmiFilterCfg)
|
||||||
|
_, _ = out.Write(transposeTemplatingCalls(datasourceContent.Bytes()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type UnhandleableArgumentError struct {
|
type UnhandleableArgumentError struct {
|
||||||
Call string
|
Call string
|
||||||
Correspondance string
|
Correspondance string
|
||||||
|
@ -327,6 +393,9 @@ func transposeTemplatingCalls(s []byte) []byte {
|
||||||
"build": func(a string) string {
|
"build": func(a string) string {
|
||||||
return fmt.Sprintf("${build.%s}", a)
|
return fmt.Sprintf("${build.%s}", a)
|
||||||
},
|
},
|
||||||
|
"data": func(a string) string {
|
||||||
|
return fmt.Sprintf("${data.%s}", a)
|
||||||
|
},
|
||||||
"template_dir": func() string {
|
"template_dir": func() string {
|
||||||
return fmt.Sprintf("${path.root}")
|
return fmt.Sprintf("${path.root}")
|
||||||
},
|
},
|
||||||
|
|
|
@ -50,6 +50,20 @@ variable "secret_account" {
|
||||||
# "timestamp" template function replacement
|
# "timestamp" template function replacement
|
||||||
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
|
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
|
||||||
|
|
||||||
|
# The amazon-ami data block is generated from your amazon builder source_ami_filter; a data
|
||||||
|
# from this block can be referenced in source and locals blocks.
|
||||||
|
# Read the documentation for data blocks here:
|
||||||
|
# https://www.packer.io/docs/templates/hcl_templates/blocks/data
|
||||||
|
data "amazon-ami" "autogenerated_1" {
|
||||||
|
filters = {
|
||||||
|
name = "ubuntu/images/*/ubuntu-xenial-16.04-amd64-server-*"
|
||||||
|
root-device-type = "ebs"
|
||||||
|
virtualization-type = "hvm"
|
||||||
|
}
|
||||||
|
most_recent = true
|
||||||
|
owners = ["099720109477"]
|
||||||
|
}
|
||||||
|
|
||||||
# source blocks are generated from your builders; a source can be referenced in
|
# source blocks are generated from your builders; a source can be referenced in
|
||||||
# build blocks. A build block runs provisioner and post-processors on a
|
# build blocks. A build block runs provisioner and post-processors on a
|
||||||
# source. Read the documentation for source blocks here:
|
# source. Read the documentation for source blocks here:
|
||||||
|
@ -65,17 +79,37 @@ source "amazon-ebs" "autogenerated_1" {
|
||||||
volume_size = 48
|
volume_size = 48
|
||||||
volume_type = "gp2"
|
volume_type = "gp2"
|
||||||
}
|
}
|
||||||
region = "${var.aws_region}"
|
region = "${var.aws_region}"
|
||||||
secret_key = "${var.aws_secret_key}"
|
secret_key = "${var.aws_secret_key}"
|
||||||
source_ami_filter {
|
source_ami = "${data.amazon-ami.autogenerated_1.id}"
|
||||||
filters = {
|
spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
|
||||||
name = "ubuntu/images/*/ubuntu-xenial-16.04-amd64-server-*"
|
spot_price = "0.0075"
|
||||||
root-device-type = "ebs"
|
ssh_interface = "session_manager"
|
||||||
virtualization-type = "hvm"
|
ssh_username = "ubuntu"
|
||||||
|
temporary_iam_instance_profile_policy_document {
|
||||||
|
Statement {
|
||||||
|
Action = ["*"]
|
||||||
|
Effect = "Allow"
|
||||||
|
Resource = ["*"]
|
||||||
}
|
}
|
||||||
most_recent = true
|
Version = "2012-10-17"
|
||||||
owners = ["099720109477"]
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
source "amazon-ebs" "named_builder" {
|
||||||
|
access_key = "${var.aws_access_key}"
|
||||||
|
ami_description = "Ubuntu 16.04 LTS - expand root partition"
|
||||||
|
ami_name = "ubuntu-16-04-test-${local.timestamp}"
|
||||||
|
encrypt_boot = true
|
||||||
|
launch_block_device_mappings {
|
||||||
|
delete_on_termination = true
|
||||||
|
device_name = "/dev/sda1"
|
||||||
|
volume_size = 48
|
||||||
|
volume_type = "gp2"
|
||||||
|
}
|
||||||
|
region = "${var.aws_region}"
|
||||||
|
secret_key = "${var.aws_secret_key}"
|
||||||
|
source_ami = "${data.amazon-ami.autogenerated_1.id}"
|
||||||
spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
|
spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
|
||||||
spot_price = "0.0075"
|
spot_price = "0.0075"
|
||||||
ssh_interface = "session_manager"
|
ssh_interface = "session_manager"
|
||||||
|
@ -94,7 +128,7 @@ source "amazon-ebs" "autogenerated_1" {
|
||||||
# documentation for build blocks can be found here:
|
# documentation for build blocks can be found here:
|
||||||
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
|
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
|
||||||
build {
|
build {
|
||||||
sources = ["source.amazon-ebs.autogenerated_1"]
|
sources = ["source.amazon-ebs.autogenerated_1", "source.amazon-ebs.named_builder"]
|
||||||
|
|
||||||
provisioner "shell" {
|
provisioner "shell" {
|
||||||
except = ["amazon-ebs"]
|
except = ["amazon-ebs"]
|
||||||
|
|
|
@ -61,6 +61,55 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ssh_interface": "session_manager"
|
"ssh_interface": "session_manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "amazon-ebs",
|
||||||
|
"name": "named_builder",
|
||||||
|
"region": "{{ user `aws_region` }}",
|
||||||
|
"secret_key": "{{ user `aws_secret_key` }}",
|
||||||
|
"access_key": "{{ user `aws_access_key` }}",
|
||||||
|
"ami_name": "ubuntu-16-04-test-{{ timestamp }}",
|
||||||
|
"ami_description": "Ubuntu 16.04 LTS - expand root partition",
|
||||||
|
"source_ami_filter": {
|
||||||
|
"filters": {
|
||||||
|
"virtualization-type": "hvm",
|
||||||
|
"name": "ubuntu/images/*/ubuntu-xenial-16.04-amd64-server-*",
|
||||||
|
"root-device-type": "ebs"
|
||||||
|
},
|
||||||
|
"owners": [
|
||||||
|
"099720109477"
|
||||||
|
],
|
||||||
|
"most_recent": true
|
||||||
|
},
|
||||||
|
"launch_block_device_mappings": [
|
||||||
|
{
|
||||||
|
"delete_on_termination": true,
|
||||||
|
"device_name": "/dev/sda1",
|
||||||
|
"volume_type": "gp2",
|
||||||
|
"volume_size": 48
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"spot_price": "0.0075",
|
||||||
|
"spot_instance_types": [
|
||||||
|
"t2.small",
|
||||||
|
"t2.medium",
|
||||||
|
"t2.large"
|
||||||
|
],
|
||||||
|
"encrypt_boot": true,
|
||||||
|
"ssh_username": "ubuntu",
|
||||||
|
"temporary_iam_instance_profile_policy_document": {
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"*"
|
||||||
|
],
|
||||||
|
"Resource": ["*"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ssh_interface": "session_manager"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"provisioners": [
|
"provisioners": [
|
||||||
|
|
Loading…
Reference in New Issue