Merge branch 'master' into merge-vsphere-builder

This commit is contained in:
Megan Marsh 2020-01-07 14:23:38 -08:00
commit 8cb1f7b1c1
504 changed files with 9578 additions and 4630 deletions

View File

@ -1,49 +1,115 @@
## 1.5.0 (Upcoming)
## 1.5.2 (Upcoming)
### IMPROVEMENTS:
* builder/amazon: Add source AMI owner ID/name to template engines [GH-8550]
* builder/azure: Set expiry for image versions in SIG [GH-8561]
* core: clean up messy log line in plugin execution. [GH-8542]
### Bug Fixes:
* builder/virtualbox-ovf: Remove config dependency from StepImport [GH-8509]
* builder/virtualbox-vm: use config as a non pointer to avoid a panic [GH-8576]
* core: Fix crash when build.sources is set to an invalid name [GH-8569]
* core: Fix loading of external plugins. GH-8543]
* post-processor/vagrant: correctly handle the diskSize property as a qemu size
string [GH-8567]
* provisioner/ansible: Fix password sanitization to account for empty string
values. [GH-8570]
## 1.5.1 (December 20, 2019)
This was a fast-follow release to fix a number of panics that we introduced when
making changes for HCL2.
### IMPROVEMENTS:
* builder/alicloud: Add show_expired option for describing images [GH-8425]
### Bug Fixes:
* builder/cloudstack: Fix panics associated with loading config [GH-8513]
* builder/hyperv/iso: Fix panics associated with loading config [GH-8513]
* builder/hyperv/vmcx: Fix panics associated with loading config [GH-8513]
* builder/jdcloud: Update jdcloud statebag to use pointers for config [GH-8518]
* builder/linode: Fix panics associated with loading config [GH-8513]
* builder/lxc: Fix panics associated with loading config [GH-8513]
* builder/lxd: Fix panics associated with loading config [GH-8513]
* builder/oneandone: Fix panics associated with loading config [GH-8513]
* builder/oracle/classic: Fix panics associated with loading config [GH-8513]
* builder/oracle/oci: Fix panics associated with loading config [GH-8513]
* builder/osc/bsuvolume: Fix panics associated with loading config [GH-8513]
* builder/parallels/pvm: Fix panics associated with loading config [GH-8513]
* builder/profitbricks: Fix panics associated with loading config [GH-8513]
* builder/scaleway: Fix panics associated with loading config [GH-8513]
* builder/vagrant: Fix panics associated with loading config [GH-8513]
* builder/virtualbox/ovf: Fix panics associated with loading config [GH-8513]
* builder/virtualbox: Configure NAT interface before forwarded port mapping
#8514
* post-processor/vagrant-cloud: Configure NAT interface before forwarded port
mapping [GH-8514]
## 1.5.0 (December 18, 2019)
### IMPROVEMENTS:
* builder/amazon: Add no_ephemeral template option to remove ephemeral drives
from launch mappings. [GH-8393]
* builder/amazon: Add validation for `subnet_id` when specifying `vpc_id`
* builder/amazon: Add validation for "subnet_id" when specifying "vpc_id"
[GH-8360] [GH-8387] [GH-8391]
* builder/amazon: allow enabling ena/sr-iov on ebssurrogate spot instances
[GH-8397]
* builder/amazon: Retry runinstances aws api call to mitigate throttling
[GH-8342]
* builder/hyperone: Update builder schema and tags [GH-8444]
* builder/qemu: Add display template option for qemu. [GH-7676]
* builder/qemu: Disk Size is now read as a string to support units. [GH-8320]
[GH-7546]
* builder/qemu: Add fixer to convert disk size from int to string [GH-8390]
* builder/qemu: Disk Size is now read as a string to support units. [GH-8320]
[GH-7546]
* builder/qemu: When a user adds a new drive in qemuargs, process it to make
sure that necessary settings are applied to that drive. [GH-8380]
* builder/vmware: Fix error message when ovftool is missing [GH-8371]
* core: Cleanup logging for external plugins [GH-8471]
* core: HCL2 template support is now in beta. [GH-8423]
* core: Interpolation within provisioners can now access build-specific values
like Host IP, communicator password, and more. [GH-7866]
* core: Various fixes to error handling. [GH-8343] [GH-8333] [GH-8316]
[GH-8354] [GH-8361] [GH-8363] [GH-8370]
* post-processor/docker-tag: Add support for multiple tags. [GH-8392]
* post-processor/shell-local: Add "valid_exit_codes" option to shell-local.
[GH-8401]
* provisioner/chef-client: Add version selection option. [GH-8468]
* provisioner/shell-local: Add "valid_exit_codes" option to shell-local.
[GH-8401]
* provisioner/shell: Add support for the `env_var_format` parameter [GH-8319]
* provisioner/shell: Add support for the "env_var_format" parameter [GH-8319]
### BUG FIXES:
* builder/amazon: Fix request retry mechanism to launch aws instance [GH-8430]
* builder/azure: Fix PollDuration option which was overriden in some clients.
[GH-8490]
* builder/hyperv: Fix bug in checking VM name that could cause flakiness if
many VMs are defined. [GH-8357]
* builder/vagrant: Use absolute path for Vagrantfile [GH-8321]
* builder/virtualbox: Fix panic in snapshot builder. [GH-8336] [GH-8329]
* communicator/winrm: Resolve ntlm nil pointer bug by bumping go-ntlmssp
dependency [GH-8369]
* communicator: Fix proxy connection settings to use `SSHProxyUsername` and
`SSHProxyPassword` where relevant instead of bastion username and password.
* communicator: Fix proxy connection settings to use "SSHProxyUsername" and
"SSHProxyPassword" where relevant instead of bastion username and password.
[GH-8375]
* core: Fix bug where Packer froze if asked to log an extremely long line
[GH-8356]
* core: Fix iso_target_path option; don't cache when target path is non-nil
[GH-8394]
* core: Return exit code 1 when builder type is not found [GH-8474]
* core: Return exit code 1 when builder type is not found [GH-8475]
* core: Update to newest version of go-tty to re-enable CTRL-S and CTRL-Q usage
[GH-8364]
### BACKWARDS INCOMPATIBILITIES:
* builder/amazon: Complete deprecation of clean_ami_name template func
[GH-8320] [GH-8193]
* builder/qemu: Disk Size is now read as a string to support units. [GH-8320]
[GH-7546]
* core: Changes have been made to both the Prepare() method signature on the
builder interface and on the Provision() method signature on the
provisioner interface. [GH-7866]
* provisioner/ansible-local: The "galaxycommand" option has been renamed to
"galaxy_command". A fixer has been written for this, which can be invoked
with `packer fix`. [GH-8411]
## 1.4.5 (November 4, 2019)

View File

@ -2,8 +2,8 @@
# builders
/builder/alicloud/ @chhaj5236
/website/source/docs/builders/alicloud* @chhaj5236
/builder/alicloud/ @chhaj5236 @alexyueer
/website/source/docs/builders/alicloud* @chhaj5236 @alexyueer
/builder/azure/ @paulmey
/website/source/docs/builders/azure* @paulmey

View File

@ -3,29 +3,42 @@
package ecs
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"runtime"
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"github.com/hashicorp/packer/template/interpolate"
"github.com/hashicorp/packer/version"
"github.com/mitchellh/go-homedir"
)
// Config of alicloud
type AlicloudAccessConfig struct {
// This is the Alicloud access key. It must be provided, but it can also be
// This is the Alicloud access key. It must be provided when profile not exist, but it can also be
// sourced from the ALICLOUD_ACCESS_KEY environment variable.
AlicloudAccessKey string `mapstructure:"access_key" required:"true"`
// This is the Alicloud secret key. It must be provided, but it can also be
AlicloudAccessKey string `mapstructure:"access_key" required:"false"`
// This is the Alicloud secret key. It must be provided when profile not exist, but it can also be
// sourced from the ALICLOUD_SECRET_KEY environment variable.
AlicloudSecretKey string `mapstructure:"secret_key" required:"true"`
// This is the Alicloud region. It must be provided, but it can also be
AlicloudSecretKey string `mapstructure:"secret_key" required:"false"`
// This is the Alicloud region. It must be provided when profile not exist, but it can also be
// sourced from the ALICLOUD_REGION environment variables.
AlicloudRegion string `mapstructure:"region" required:"true"`
AlicloudRegion string `mapstructure:"region" required:"false"`
// The region validation can be skipped if this value is true, the default
// value is false.
AlicloudSkipValidation bool `mapstructure:"skip_region_validation" required:"false"`
// The image validation can be skipped if this value is true, the default
// value is false.
AlicloudSkipImageValidation bool `mapstructure:"skip_image_validation" required:"false"`
// This is th Alicloud profile. If access_key not exist, is must be provided, but it can also be
// sourced from the ALICLOUD_PROFILE environment variables.
AlicloudProfile string `mapstructure:"profile" required:"false"`
// This is the Alicloud shared credentials file path. If this file path exist, os will read access key
// and secret key from this file.
AlicloudSharedCredentialsFile string `mapstructure:"shared_credentials_file" required:"false"`
// STS access token, can be set through template or by exporting as
// environment variable such as `export SECURITY_TOKEN=value`.
SecurityToken string `mapstructure:"security_token" required:"false"`
@ -45,8 +58,22 @@ func (c *AlicloudAccessConfig) Client() (*ClientWrapper, error) {
c.SecurityToken = os.Getenv("SECURITY_TOKEN")
}
client, err := ecs.NewClientWithStsToken(c.AlicloudRegion, c.AlicloudAccessKey,
c.AlicloudSecretKey, c.SecurityToken)
var getProviderConfig = func(str string, key string) string {
value, err := getConfigFromProfile(c, key)
if err == nil && value != nil {
str = value.(string)
}
return str
}
if c.AlicloudAccessKey == "" || c.AlicloudSecretKey == "" {
c.AlicloudAccessKey = getProviderConfig(c.AlicloudAccessKey, "access_key_id")
c.AlicloudSecretKey = getProviderConfig(c.AlicloudSecretKey, "access_key_secret")
c.AlicloudRegion = getProviderConfig(c.AlicloudRegion, "region_id")
c.SecurityToken = getProviderConfig(c.SecurityToken, "sts_token")
}
client, err := ecs.NewClientWithStsToken(c.AlicloudRegion, c.AlicloudAccessKey, c.AlicloudSecretKey, c.SecurityToken)
if err != nil {
return nil, err
}
@ -86,7 +113,13 @@ func (c *AlicloudAccessConfig) Config() error {
if c.AlicloudSecretKey == "" {
c.AlicloudSecretKey = os.Getenv("ALICLOUD_SECRET_KEY")
}
if c.AlicloudAccessKey == "" || c.AlicloudSecretKey == "" {
if c.AlicloudProfile == "" {
c.AlicloudProfile = os.Getenv("ALICLOUD_PROFILE")
}
if c.AlicloudSharedCredentialsFile == "" {
c.AlicloudSharedCredentialsFile = os.Getenv("ALICLOUD_SHARED_CREDENTIALS_FILE")
}
if (c.AlicloudAccessKey == "" || c.AlicloudSecretKey == "") && c.AlicloudProfile == "" {
return fmt.Errorf("ALICLOUD_ACCESS_KEY and ALICLOUD_SECRET_KEY must be set in template file or environment variables.")
}
return nil
@ -128,3 +161,66 @@ func (c *AlicloudAccessConfig) getSupportedRegions() ([]string, error) {
return validRegions, nil
}
func getConfigFromProfile(c *AlicloudAccessConfig, ProfileKey string) (interface{}, error) {
providerConfig := make(map[string]interface{})
current := c.AlicloudProfile
if current != "" {
profilePath, err := homedir.Expand(c.AlicloudSharedCredentialsFile)
if err != nil {
return nil, err
}
if profilePath == "" {
profilePath = fmt.Sprintf("%s/.aliyun/config.json", os.Getenv("HOME"))
if runtime.GOOS == "windows" {
profilePath = fmt.Sprintf("%s/.aliyun/config.json", os.Getenv("USERPROFILE"))
}
}
_, err = os.Stat(profilePath)
if !os.IsNotExist(err) {
data, err := ioutil.ReadFile(profilePath)
if err != nil {
return nil, err
}
config := map[string]interface{}{}
err = json.Unmarshal(data, &config)
if err != nil {
return nil, err
}
for _, v := range config["profiles"].([]interface{}) {
if current == v.(map[string]interface{})["name"] {
providerConfig = v.(map[string]interface{})
}
}
}
}
mode := ""
if v, ok := providerConfig["mode"]; ok {
mode = v.(string)
} else {
return v, nil
}
switch ProfileKey {
case "access_key_id", "access_key_secret":
if mode == "EcsRamRole" {
return "", nil
}
case "ram_role_name":
if mode != "EcsRamRole" {
return "", nil
}
case "sts_token":
if mode != "StsToken" {
return "", nil
}
case "ram_role_arn", "ram_session_name":
if mode != "RamRoleArn" {
return "", nil
}
case "expired_seconds":
if mode != "RamRoleArn" {
return float64(0), nil
}
}
return providerConfig[ProfileKey], nil
}

View File

@ -32,5 +32,21 @@ func TestAlicloudAccessConfigPrepareRegion(t *testing.T) {
t.Fatalf("shouldn't have err: %s", err)
}
c.AlicloudAccessKey = ""
if err := c.Prepare(nil); err == nil {
t.Fatalf("should have err")
}
c.AlicloudProfile = "default"
if err := c.Prepare(nil); err != nil {
t.Fatalf("shouldn't have err: %s", err)
}
c.AlicloudProfile = ""
os.Setenv("ALICLOUD_PROFILE", "default")
if err := c.Prepare(nil); err != nil {
t.Fatalf("shouldn't have err: %s", err)
}
c.AlicloudSkipValidation = false
}

View File

@ -8,6 +8,7 @@ import (
"context"
"fmt"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
@ -41,7 +42,9 @@ const (
ALICLOUD_DEFAULT_LONG_TIMEOUT = 3600
)
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
err := config.Decode(&b.config, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &b.config.ctx,
@ -53,7 +56,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}, raws...)
b.config.ctx.EnableEnv = true
if err != nil {
return nil, err
return nil, nil, err
}
if b.config.PackerConfig.PackerForce {
@ -68,11 +71,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...)
if errs != nil && len(errs.Errors) > 0 {
return nil, errs
return nil, nil, errs
}
packer.LogSecretFilter.Set(b.config.AlicloudAccessKey, b.config.AlicloudSecretKey)
return nil, nil
return nil, nil, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {

View File

@ -22,10 +22,13 @@ type FlatAlicloudDiskDevice struct {
// FlatMapstructure returns a new FlatAlicloudDiskDevice.
// FlatAlicloudDiskDevice is an auto-generated flat version of AlicloudDiskDevice.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*AlicloudDiskDevice) FlatMapstructure() interface{} { return new(FlatAlicloudDiskDevice) }
func (*AlicloudDiskDevice) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatAlicloudDiskDevice)
}
// HCL2Spec returns the hcldec.Spec of a FlatAlicloudDiskDevice.
// This spec is used by HCL to read the fields of FlatAlicloudDiskDevice.
// HCL2Spec returns the hcl spec of a AlicloudDiskDevice.
// This spec is used by HCL to read the fields of AlicloudDiskDevice.
// The decoded values from this spec will then be applied to a FlatAlicloudDiskDevice.
func (*FlatAlicloudDiskDevice) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"disk_name": &hcldec.AttrSpec{Name: "disk_name", Type: cty.String, Required: false},
@ -50,10 +53,13 @@ type FlatConfig struct {
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
AlicloudAccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key"`
AlicloudSecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
AlicloudRegion *string `mapstructure:"region" required:"true" cty:"region"`
AlicloudAccessKey *string `mapstructure:"access_key" required:"false" cty:"access_key"`
AlicloudSecretKey *string `mapstructure:"secret_key" required:"false" cty:"secret_key"`
AlicloudRegion *string `mapstructure:"region" required:"false" cty:"region"`
AlicloudSkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
AlicloudSkipImageValidation *bool `mapstructure:"skip_image_validation" required:"false" cty:"skip_image_validation"`
AlicloudProfile *string `mapstructure:"profile" required:"false" cty:"profile"`
AlicloudSharedCredentialsFile *string `mapstructure:"shared_credentials_file" required:"false" cty:"shared_credentials_file"`
SecurityToken *string `mapstructure:"security_token" required:"false" cty:"security_token"`
AlicloudImageName *string `mapstructure:"image_name" required:"true" cty:"image_name"`
AlicloudImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version"`
@ -121,8 +127,8 @@ type FlatConfig struct {
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
@ -137,10 +143,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
@ -154,6 +163,9 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
"skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false},
"skip_image_validation": &hcldec.AttrSpec{Name: "skip_image_validation", Type: cty.Bool, Required: false},
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
"shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false},
"security_token": &hcldec.AttrSpec{Name: "security_token", Type: cty.String, Required: false},
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
@ -169,7 +181,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"image_ignore_data_disks": &hcldec.AttrSpec{Name: "image_ignore_data_disks", Type: cty.Bool, Required: false},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"system_disk_mapping": &hcldec.BlockSpec{TypeName: "system_disk_mapping", Nested: hcldec.ObjectSpec((*FlatAlicloudDiskDevice)(nil).HCL2Spec())},
"image_disk_mappings": &hcldec.BlockListSpec{TypeName: "image_disk_mappings", Nested: &hcldec.BlockSpec{TypeName: "image_disk_mappings", Nested: hcldec.ObjectSpec((*FlatAlicloudDiskDevice)(nil).HCL2Spec())}},
"image_disk_mappings": &hcldec.BlockListSpec{TypeName: "image_disk_mappings", Nested: hcldec.ObjectSpec((*FlatAlicloudDiskDevice)(nil).HCL2Spec())},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
"zone_id": &hcldec.AttrSpec{Name: "zone_id", Type: cty.String, Required: false},
"io_optimized": &hcldec.AttrSpec{Name: "io_optimized", Type: cty.Bool, Required: false},

View File

@ -35,7 +35,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) {
"access_key": []string{},
}
warnings, err := b.Prepare(c)
_, warnings, err := b.Prepare(c)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -50,7 +50,7 @@ func TestBuilderPrepare_ECSImageName(t *testing.T) {
// Test good
config["image_name"] = "ecs.n1.tiny"
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -61,7 +61,7 @@ func TestBuilderPrepare_ECSImageName(t *testing.T) {
// Test bad
config["ecs_image_name"] = "foo {{"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -72,7 +72,7 @@ func TestBuilderPrepare_ECSImageName(t *testing.T) {
// Test bad
delete(config, "image_name")
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -87,7 +87,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -120,7 +120,7 @@ func TestBuilderPrepare_Devices(t *testing.T) {
"disk_device": "/dev/xvdc",
},
}
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -160,7 +160,7 @@ func TestBuilderPrepare_IgnoreDataDisks(t *testing.T) {
var b Builder
config := testBuilderConfig()
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -173,7 +173,7 @@ func TestBuilderPrepare_IgnoreDataDisks(t *testing.T) {
}
config["image_ignore_data_disks"] = "false"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -186,7 +186,7 @@ func TestBuilderPrepare_IgnoreDataDisks(t *testing.T) {
}
config["image_ignore_data_disks"] = "true"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -203,7 +203,7 @@ func TestBuilderPrepare_WaitSnapshotReadyTimeout(t *testing.T) {
var b Builder
config := testBuilderConfig()
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -219,7 +219,7 @@ func TestBuilderPrepare_WaitSnapshotReadyTimeout(t *testing.T) {
}
config["wait_snapshot_ready_timeout"] = ALICLOUD_DEFAULT_TIMEOUT
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}

View File

@ -33,14 +33,11 @@ func TestWaitForExpectedExceedRetryTimes(t *testing.T) {
waitDone <- true
}()
timeTolerance := 1 * time.Second
select {
case <-waitDone:
if iter != defaultRetryTimes {
t.Fatalf("WaitForExpected should terminate at the %d iterations", defaultRetryTimes)
}
case <-time.After(defaultRetryTimes*defaultRetryInterval + timeTolerance):
t.Fatalf("WaitForExpected should terminate within %f seconds", (defaultRetryTimes*defaultRetryInterval + timeTolerance).Seconds())
}
}

View File

@ -21,6 +21,9 @@ func (s *stepCheckAlicloudSourceImage) Run(ctx context.Context, state multistep.
describeImagesRequest := ecs.CreateDescribeImagesRequest()
describeImagesRequest.RegionId = config.AlicloudRegion
describeImagesRequest.ImageId = config.AlicloudSourceImage
if config.AlicloudSkipImageValidation {
describeImagesRequest.ShowExpired = "true"
}
imagesResponse, err := client.DescribeImages(describeImagesRequest)
if err != nil {
return halt(state, err, "Error querying alicloud image")

View File

@ -36,7 +36,7 @@ func (s *stepConfigAlicloudSecurityGroup) Run(ctx context.Context, state multist
if len(s.SecurityGroupId) != 0 {
describeSecurityGroupsRequest := ecs.CreateDescribeSecurityGroupsRequest()
describeSecurityGroupsRequest.RegionId = s.RegionId
describeSecurityGroupsRequest.SecurityGroupId = s.SecurityGroupId
if networkType == InstanceNetworkVpc {
vpcId := state.Get("vpcid").(string)
describeSecurityGroupsRequest.VpcId = vpcId

View File

@ -77,6 +77,9 @@ func (s *stepCreateAlicloudInstance) Run(ctx context.Context, state multistep.St
ui.Message(fmt.Sprintf("Created instance: %s", instanceId))
s.instance = &instances.Instances.Instance[0]
state.Put("instance", s.instance)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", instanceId)
return multistep.ActionContinue
}

View File

@ -3,9 +3,9 @@ package ecs
import (
"context"
"fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"

View File

@ -13,6 +13,7 @@ import (
"runtime"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/hcl/v2/hcldec"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/common/chroot"
@ -182,7 +183,9 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs = awscommon.TemplateFuncs
err := config.Decode(&b.config, &config.DecodeOpts{
Interpolate: true,
@ -201,7 +204,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
},
}, raws...)
if err != nil {
return nil, err
return nil, nil, err
}
if b.config.Architecture == "" {
@ -319,11 +322,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return warns, errs
return nil, warns, errs
}
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
return warns, nil
return nil, warns, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {

View File

@ -72,10 +72,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
@ -93,7 +96,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false},
"ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false},
"skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false},
"tags": &hcldec.BlockAttrsSpec{TypeName: "common.TagMap", ElementType: cty.String, Required: false},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
@ -102,7 +105,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"region_kms_key_ids": &hcldec.BlockAttrsSpec{TypeName: "region_kms_key_ids", ElementType: cty.String, Required: false},
"skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false},
"snapshot_tags": &hcldec.BlockAttrsSpec{TypeName: "common.TagMap", ElementType: cty.String, Required: false},
"snapshot_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
"snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false},
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
@ -116,7 +119,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: &hcldec.BlockSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())}},
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
"chroot_mounts": &hcldec.BlockListSpec{TypeName: "chroot_mounts", Nested: &hcldec.AttrSpec{Name: "chroot_mounts", Type: cty.List(cty.String), Required: false}},
"command_wrapper": &hcldec.AttrSpec{Name: "command_wrapper", Type: cty.String, Required: false},
"copy_files": &hcldec.AttrSpec{Name: "copy_files", Type: cty.List(cty.String), Required: false},
@ -133,7 +136,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"root_volume_type": &hcldec.AttrSpec{Name: "root_volume_type", Type: cty.String, Required: false},
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
"source_ami_filter": &hcldec.BlockSpec{TypeName: "source_ami_filter", Nested: hcldec.ObjectSpec((*common.FlatAmiFilterOptions)(nil).HCL2Spec())},
"root_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "common.TagMap", ElementType: cty.String, Required: false},
"root_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "root_volume_tags", ElementType: cty.String, Required: false},
"ami_architecture": &hcldec.AttrSpec{Name: "ami_architecture", Type: cty.String, Required: false},
}
return s

View File

@ -31,7 +31,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test good
config["ami_name"] = "foo"
config["skip_region_validation"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -42,7 +42,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
config["ami_name"] = "foo {{"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -53,7 +53,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
delete(config, "ami_name")
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -67,7 +67,7 @@ func TestBuilderPrepare_ChrootMounts(t *testing.T) {
config := testConfig()
config["chroot_mounts"] = nil
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -83,7 +83,7 @@ func TestBuilderPrepare_ChrootMountsBadDefaults(t *testing.T) {
config["chroot_mounts"] = [][]string{
{"bad"},
}
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -96,7 +96,7 @@ func TestBuilderPrepare_SourceAmi(t *testing.T) {
config := testConfig()
config["source_ami"] = ""
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -105,7 +105,7 @@ func TestBuilderPrepare_SourceAmi(t *testing.T) {
}
config["source_ami"] = "foo"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -119,7 +119,7 @@ func TestBuilderPrepare_CommandWrapper(t *testing.T) {
config := testConfig()
config["command_wrapper"] = "echo hi; {{.Command}}"
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -132,7 +132,7 @@ func TestBuilderPrepare_CopyFiles(t *testing.T) {
b := &Builder{}
config := testConfig()
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -150,7 +150,7 @@ func TestBuilderPrepare_CopyFilesNoDefault(t *testing.T) {
config := testConfig()
config["copy_files"] = []string{}
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -171,7 +171,7 @@ func TestBuilderPrepare_RootDeviceNameAndAMIMappings(t *testing.T) {
config["root_device_name"] = "/dev/sda"
config["ami_block_device_mappings"] = []interface{}{map[string]string{}}
config["root_volume_size"] = 15
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) == 0 {
t.Fatal("Missing warning, stating block device mappings will be overwritten")
} else if len(warnings) > 1 {
@ -187,7 +187,7 @@ func TestBuilderPrepare_AMIMappingsNoRootDeviceName(t *testing.T) {
config := testConfig()
config["ami_block_device_mappings"] = []interface{}{map[string]string{}}
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -201,7 +201,7 @@ func TestBuilderPrepare_RootDeviceNameNoAMIMappings(t *testing.T) {
config := testConfig()
config["root_device_name"] = "/dev/sda"
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}

View File

@ -18,10 +18,13 @@ type FlatVaultAWSEngineOptions struct {
// FlatMapstructure returns a new FlatVaultAWSEngineOptions.
// FlatVaultAWSEngineOptions is an auto-generated flat version of VaultAWSEngineOptions.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*VaultAWSEngineOptions) FlatMapstructure() interface{} { return new(FlatVaultAWSEngineOptions) }
func (*VaultAWSEngineOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatVaultAWSEngineOptions)
}
// HCL2Spec returns the hcldec.Spec of a FlatVaultAWSEngineOptions.
// This spec is used by HCL to read the fields of FlatVaultAWSEngineOptions.
// HCL2Spec returns the hcl spec of a VaultAWSEngineOptions.
// This spec is used by HCL to read the fields of VaultAWSEngineOptions.
// The decoded values from this spec will then be applied to a FlatVaultAWSEngineOptions.
func (*FlatVaultAWSEngineOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"name": &hcldec.AttrSpec{Name: "name", Type: cty.String, Required: false},

View File

@ -24,10 +24,13 @@ type FlatBlockDevice struct {
// FlatMapstructure returns a new FlatBlockDevice.
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*BlockDevice) FlatMapstructure() interface{} { return new(FlatBlockDevice) }
func (*BlockDevice) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatBlockDevice)
}
// HCL2Spec returns the hcldec.Spec of a FlatBlockDevice.
// This spec is used by HCL to read the fields of FlatBlockDevice.
// HCL2Spec returns the hcl spec of a BlockDevice.
// This spec is used by HCL to read the fields of BlockDevice.
// The decoded values from this spec will then be applied to a FlatBlockDevice.
func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"delete_on_termination": &hcldec.AttrSpec{Name: "delete_on_termination", Type: cty.Bool, Required: false},

View File

@ -7,10 +7,12 @@ import (
)
type BuildInfoTemplate struct {
BuildRegion string
SourceAMI string
SourceAMIName string
SourceAMITags map[string]string
BuildRegion string
SourceAMI string
SourceAMIName string
SourceAMIOwner string
SourceAMIOwnerName string
SourceAMITags map[string]string
}
func extractBuildInfo(region string, state multistep.StateBag) *BuildInfoTemplate {
@ -28,9 +30,11 @@ func extractBuildInfo(region string, state multistep.StateBag) *BuildInfoTemplat
}
return &BuildInfoTemplate{
BuildRegion: region,
SourceAMI: aws.StringValue(sourceAMI.ImageId),
SourceAMIName: aws.StringValue(sourceAMI.Name),
SourceAMITags: sourceAMITags,
BuildRegion: region,
SourceAMI: aws.StringValue(sourceAMI.ImageId),
SourceAMIName: aws.StringValue(sourceAMI.Name),
SourceAMIOwner: aws.StringValue(sourceAMI.OwnerId),
SourceAMIOwnerName: aws.StringValue(sourceAMI.ImageOwnerAlias),
SourceAMITags: sourceAMITags,
}
}

View File

@ -11,8 +11,10 @@ import (
func testImage() *ec2.Image {
return &ec2.Image{
ImageId: aws.String("ami-abcd1234"),
Name: aws.String("ami_test_name"),
ImageId: aws.String("ami-abcd1234"),
Name: aws.String("ami_test_name"),
OwnerId: aws.String("ami_test_owner_id"),
ImageOwnerAlias: aws.String("ami_test_owner_alias"),
Tags: []*ec2.Tag{
{
Key: aws.String("key-1"),
@ -49,9 +51,11 @@ func TestInterpolateBuildInfo_extractBuildInfo_withSourceImage(t *testing.T) {
buildInfo := extractBuildInfo("foo", state)
expected := BuildInfoTemplate{
BuildRegion: "foo",
SourceAMI: "ami-abcd1234",
SourceAMIName: "ami_test_name",
BuildRegion: "foo",
SourceAMI: "ami-abcd1234",
SourceAMIName: "ami_test_name",
SourceAMIOwner: "ami_test_owner_id",
SourceAMIOwnerName: "ami_test_owner_alias",
SourceAMITags: map[string]string{
"key-1": "value-1",
"key-2": "value-2",

View File

@ -145,6 +145,8 @@ type RunConfig struct {
// profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
// to launch the EC2 instance with.
IamInstanceProfile string `mapstructure:"iam_instance_profile" required:"false"`
// Whether or not to check if the IAM instance profile exists. Defaults to false
SkipProfileValidation bool `mapstructure:"skip_profile_validation" required:"false"`
// Temporary IAM instance profile policy document
// If IamInstanceProfile is specified it will be used instead. Example:
//
@ -375,8 +377,20 @@ type RunConfig struct {
WindowsPasswordTimeout time.Duration `mapstructure:"windows_password_timeout" required:"false"`
// Communicator settings
Comm communicator.Config `mapstructure:",squash"`
SSHInterface string `mapstructure:"ssh_interface"`
Comm communicator.Config `mapstructure:",squash"`
// One of `public_ip`, `private_ip`, `public_dns`, or `private_dns`. If
// set, either the public IP address, private IP address, public DNS name
// or private DNS name will be used as the host for SSH. The default behaviour
// if inside a VPC is to use the public IP address if available, otherwise
// the private IP address will be used. If not in a VPC the public DNS name
// will be used. Also works for WinRM.
//
// Where Packer is configured for an outbound proxy but WinRM traffic
// should be direct, `ssh_interface` must be set to `private_dns` and
// `<region>.compute.internal` included in the `NO_PROXY` environment
// variable.
SSHInterface string `mapstructure:"ssh_interface"`
}
func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {

View File

@ -17,10 +17,13 @@ type FlatAmiFilterOptions struct {
// FlatMapstructure returns a new FlatAmiFilterOptions.
// FlatAmiFilterOptions is an auto-generated flat version of AmiFilterOptions.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*AmiFilterOptions) FlatMapstructure() interface{} { return new(FlatAmiFilterOptions) }
func (*AmiFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatAmiFilterOptions)
}
// HCL2Spec returns the hcldec.Spec of a FlatAmiFilterOptions.
// This spec is used by HCL to read the fields of FlatAmiFilterOptions.
// HCL2Spec returns the hcl spec of a AmiFilterOptions.
// This spec is used by HCL to read the fields of AmiFilterOptions.
// The decoded values from this spec will then be applied to a FlatAmiFilterOptions.
func (*FlatAmiFilterOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
@ -40,14 +43,17 @@ type FlatPolicyDocument struct {
// FlatMapstructure returns a new FlatPolicyDocument.
// FlatPolicyDocument is an auto-generated flat version of PolicyDocument.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*PolicyDocument) FlatMapstructure() interface{} { return new(FlatPolicyDocument) }
func (*PolicyDocument) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatPolicyDocument)
}
// HCL2Spec returns the hcldec.Spec of a FlatPolicyDocument.
// This spec is used by HCL to read the fields of FlatPolicyDocument.
// HCL2Spec returns the hcl spec of a PolicyDocument.
// This spec is used by HCL to read the fields of PolicyDocument.
// The decoded values from this spec will then be applied to a FlatPolicyDocument.
func (*FlatPolicyDocument) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"version": &hcldec.AttrSpec{Name: "version", Type: cty.String, Required: false},
"statement": &hcldec.BlockListSpec{TypeName: "statement", Nested: &hcldec.BlockSpec{TypeName: "statement", Nested: hcldec.ObjectSpec((*FlatStatement)(nil).HCL2Spec())}},
"statement": &hcldec.BlockListSpec{TypeName: "statement", Nested: hcldec.ObjectSpec((*FlatStatement)(nil).HCL2Spec())},
}
return s
}
@ -61,12 +67,13 @@ type FlatSecurityGroupFilterOptions struct {
// FlatMapstructure returns a new FlatSecurityGroupFilterOptions.
// FlatSecurityGroupFilterOptions is an auto-generated flat version of SecurityGroupFilterOptions.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*SecurityGroupFilterOptions) FlatMapstructure() interface{} {
func (*SecurityGroupFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatSecurityGroupFilterOptions)
}
// HCL2Spec returns the hcldec.Spec of a FlatSecurityGroupFilterOptions.
// This spec is used by HCL to read the fields of FlatSecurityGroupFilterOptions.
// HCL2Spec returns the hcl spec of a SecurityGroupFilterOptions.
// This spec is used by HCL to read the fields of SecurityGroupFilterOptions.
// The decoded values from this spec will then be applied to a FlatSecurityGroupFilterOptions.
func (*FlatSecurityGroupFilterOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
@ -85,10 +92,13 @@ type FlatStatement struct {
// FlatMapstructure returns a new FlatStatement.
// FlatStatement is an auto-generated flat version of Statement.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Statement) FlatMapstructure() interface{} { return new(FlatStatement) }
func (*Statement) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatStatement)
}
// HCL2Spec returns the hcldec.Spec of a FlatStatement.
// This spec is used by HCL to read the fields of FlatStatement.
// HCL2Spec returns the hcl spec of a Statement.
// This spec is used by HCL to read the fields of Statement.
// The decoded values from this spec will then be applied to a FlatStatement.
func (*FlatStatement) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"effect": &hcldec.AttrSpec{Name: "effect", Type: cty.String, Required: false},
@ -109,10 +119,13 @@ type FlatSubnetFilterOptions struct {
// FlatMapstructure returns a new FlatSubnetFilterOptions.
// FlatSubnetFilterOptions is an auto-generated flat version of SubnetFilterOptions.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*SubnetFilterOptions) FlatMapstructure() interface{} { return new(FlatSubnetFilterOptions) }
func (*SubnetFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatSubnetFilterOptions)
}
// HCL2Spec returns the hcldec.Spec of a FlatSubnetFilterOptions.
// This spec is used by HCL to read the fields of FlatSubnetFilterOptions.
// HCL2Spec returns the hcl spec of a SubnetFilterOptions.
// This spec is used by HCL to read the fields of SubnetFilterOptions.
// The decoded values from this spec will then be applied to a FlatSubnetFilterOptions.
func (*FlatSubnetFilterOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
@ -131,10 +144,13 @@ type FlatVpcFilterOptions struct {
// FlatMapstructure returns a new FlatVpcFilterOptions.
// FlatVpcFilterOptions is an auto-generated flat version of VpcFilterOptions.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*VpcFilterOptions) FlatMapstructure() interface{} { return new(FlatVpcFilterOptions) }
func (*VpcFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatVpcFilterOptions)
}
// HCL2Spec returns the hcldec.Spec of a FlatVpcFilterOptions.
// This spec is used by HCL to read the fields of FlatVpcFilterOptions.
// HCL2Spec returns the hcl spec of a VpcFilterOptions.
// This spec is used by HCL to read the fields of VpcFilterOptions.
// The decoded values from this spec will then be applied to a FlatVpcFilterOptions.
func (*FlatVpcFilterOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},

View File

@ -13,7 +13,6 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/common/retry"
commonhelper "github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
@ -91,16 +90,13 @@ WaitLoop:
"Password (since debug is enabled): %s", s.Comm.WinRMPassword))
}
// store so that we can access this later during provisioning
commonhelper.SetSharedState("winrm_password", s.Comm.WinRMPassword, s.BuildName)
state.Put("winrm_password", s.Comm.WinRMPassword)
packer.LogSecretFilter.Set(s.Comm.WinRMPassword)
return multistep.ActionContinue
}
func (s *StepGetPassword) Cleanup(multistep.StateBag) {
commonhelper.RemoveSharedStateFile("winrm_password", s.BuildName)
}
func (s *StepGetPassword) Cleanup(multistep.StateBag) {}
func (s *StepGetPassword) waitForPassword(ctx context.Context, state multistep.StateBag) (string, error) {
ec2conn := state.Get("ec2").(*ec2.EC2)

View File

@ -2,11 +2,10 @@ package common
import (
"context"
"encoding/json"
"fmt"
"log"
"encoding/json"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/packer/common/uuid"
@ -16,6 +15,7 @@ import (
type StepIamInstanceProfile struct {
IamInstanceProfile string
SkipProfileValidation bool
TemporaryIamInstanceProfilePolicyDocument *PolicyDocument
createdInstanceProfileName string
createdRoleName string
@ -30,16 +30,18 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB
state.Put("iamInstanceProfile", "")
if len(s.IamInstanceProfile) > 0 {
_, err := iamsvc.GetInstanceProfile(
&iam.GetInstanceProfileInput{
InstanceProfileName: aws.String(s.IamInstanceProfile),
},
)
if err != nil {
err := fmt.Errorf("Couldn't find specified instance profile: %s", err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
if !s.SkipProfileValidation {
_, err := iamsvc.GetInstanceProfile(
&iam.GetInstanceProfileInput{
InstanceProfileName: aws.String(s.IamInstanceProfile),
},
)
if err != nil {
err := fmt.Errorf("Couldn't find specified instance profile: %s", err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
}
log.Printf("Using specified instance profile: %v", s.IamInstanceProfile)
state.Put("iamInstanceProfile", s.IamInstanceProfile)

View File

@ -280,6 +280,9 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
}
state.Put("instance", instance)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", instance.InstanceId)
// If we're in a region that doesn't support tagging on instance creation,
// do that now.

View File

@ -441,6 +441,9 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
}
state.Put("instance", instance)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", instance.InstanceId)
return multistep.ActionContinue
}

View File

@ -14,6 +14,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/hcl/v2/hcldec"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
@ -72,7 +73,9 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs = awscommon.TemplateFuncs
err := config.Decode(&b.config, &config.DecodeOpts{
Interpolate: true,
@ -89,7 +92,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
},
}, raws...)
if err != nil {
return nil, err
return nil, nil, err
}
if b.config.PackerConfig.PackerForce {
@ -123,11 +126,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return warns, errs
return nil, warns, errs
}
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
return warns, nil
return nil, warns, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
@ -234,6 +237,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
},
&awscommon.StepIamInstanceProfile{
IamInstanceProfile: b.config.IamInstanceProfile,
SkipProfileValidation: b.config.SkipProfileValidation,
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
},
&awscommon.StepCleanupVolumes{

View File

@ -55,6 +55,7 @@ type FlatConfig struct {
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
@ -106,8 +107,8 @@ type FlatConfig struct {
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
@ -126,10 +127,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
@ -158,7 +162,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false},
"ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false},
"ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false},
"tags": &hcldec.BlockAttrsSpec{TypeName: "common.TagMap", ElementType: cty.String, Required: false},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
@ -167,7 +171,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"region_kms_key_ids": &hcldec.BlockAttrsSpec{TypeName: "region_kms_key_ids", ElementType: cty.String, Required: false},
"skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false},
"snapshot_tags": &hcldec.BlockAttrsSpec{TypeName: "common.TagMap", ElementType: cty.String, Required: false},
"snapshot_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
"snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false},
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
@ -177,6 +181,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false},
"enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false},
"iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false},
"skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false},
"temporary_iam_instance_profile_policy_document": &hcldec.BlockSpec{TypeName: "temporary_iam_instance_profile_policy_document", Nested: hcldec.ObjectSpec((*common.FlatPolicyDocument)(nil).HCL2Spec())},
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
"instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false},
@ -239,9 +244,9 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
"ssh_interface": &hcldec.AttrSpec{Name: "ssh_interface", Type: cty.String, Required: false},
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: &hcldec.BlockSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())}},
"launch_block_device_mappings": &hcldec.BlockListSpec{TypeName: "launch_block_device_mappings", Nested: &hcldec.BlockSpec{TypeName: "launch_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())}},
"run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "common.TagMap", ElementType: cty.String, Required: false},
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
"launch_block_device_mappings": &hcldec.BlockListSpec{TypeName: "launch_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
"run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "run_volume_tags", ElementType: cty.String, Required: false},
"no_ephemeral": &hcldec.AttrSpec{Name: "no_ephemeral", Type: cty.Bool, Required: false},
}
return s

View File

@ -32,7 +32,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) {
"access_key": []string{},
}
warnings, err := b.Prepare(c)
_, warnings, err := b.Prepare(c)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -48,7 +48,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test good
config["ami_name"] = "foo"
config["skip_region_validation"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -59,7 +59,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
config["ami_name"] = "foo {{"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -70,7 +70,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
delete(config, "ami_name")
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -85,7 +85,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -101,7 +101,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) {
// Test good
config["shutdown_behavior"] = "terminate"
config["skip_region_validation"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -111,7 +111,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) {
// Test good
config["shutdown_behavior"] = "stop"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -121,7 +121,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) {
// Test bad
config["shutdown_behavior"] = "foobar"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}

View File

@ -1,4 +1,5 @@
//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config,RootBlockDevice,BlockDevice
// The ebssurrogate package contains a packer.Builder implementation that
// builds a new EBS-backed AMI using an ephemeral instance.
@ -11,6 +12,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/hcl/v2/hcldec"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
@ -70,7 +72,9 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs = awscommon.TemplateFuncs
err := config.Decode(&b.config, &config.DecodeOpts{
Interpolate: true,
@ -87,7 +91,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
},
}, raws...)
if err != nil {
return nil, err
return nil, nil, err
}
if b.config.PackerConfig.PackerForce {
@ -145,12 +149,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
errs = packer.MultiErrorAppend(errs, errors.New(`The only valid ami_architecture values are "x86_64" and "arm64"`))
}
if errs != nil && len(errs.Errors) > 0 {
return warns, errs
return nil, warns, errs
}
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
return warns, nil
return nil, warns, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
@ -257,6 +261,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
},
&awscommon.StepIamInstanceProfile{
IamInstanceProfile: b.config.IamInstanceProfile,
SkipProfileValidation: b.config.SkipProfileValidation,
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
},
&awscommon.StepCleanupVolumes{

View File

@ -0,0 +1,331 @@
// Code generated by "mapstructure-to-hcl2 -type Config,RootBlockDevice,BlockDevice"; DO NOT EDIT.
package ebssurrogate
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/zclconf/go-cty/cty"
)
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatBlockDevice struct {
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination"`
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name"`
Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted"`
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops"`
NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device"`
SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id"`
VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name"`
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type"`
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size"`
KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
OmitFromArtifact *bool `mapstructure:"omit_from_artifact" cty:"omit_from_artifact"`
}
// FlatMapstructure returns a new FlatBlockDevice.
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*BlockDevice) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatBlockDevice)
}
// HCL2Spec returns the hcl spec of a BlockDevice.
// This spec is used by HCL to read the fields of BlockDevice.
// The decoded values from this spec will then be applied to a FlatBlockDevice.
func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"delete_on_termination": &hcldec.AttrSpec{Name: "delete_on_termination", Type: cty.Bool, Required: false},
"device_name": &hcldec.AttrSpec{Name: "device_name", Type: cty.String, Required: false},
"encrypted": &hcldec.AttrSpec{Name: "encrypted", Type: cty.Bool, Required: false},
"iops": &hcldec.AttrSpec{Name: "iops", Type: cty.Number, Required: false},
"no_device": &hcldec.AttrSpec{Name: "no_device", Type: cty.Bool, Required: false},
"snapshot_id": &hcldec.AttrSpec{Name: "snapshot_id", Type: cty.String, Required: false},
"virtual_name": &hcldec.AttrSpec{Name: "virtual_name", Type: cty.String, Required: false},
"volume_type": &hcldec.AttrSpec{Name: "volume_type", Type: cty.String, Required: false},
"volume_size": &hcldec.AttrSpec{Name: "volume_size", Type: cty.Number, Required: false},
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"omit_from_artifact": &hcldec.AttrSpec{Name: "omit_from_artifact", Type: cty.Bool, Required: false},
}
return s
}
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key"`
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check"`
Token *string `mapstructure:"token" required:"false" cty:"token"`
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine"`
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address"`
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone"`
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes"`
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter"`
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name"`
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description"`
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type"`
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users"`
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups"`
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes"`
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions"`
AMITags common.TagMap `mapstructure:"tags" required:"false" cty:"tags"`
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
SnapshotTags common.TagMap `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"`
LaunchMappings []FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings"`
RootDevice *FlatRootBlockDevice `mapstructure:"ami_root_device" required:"true" cty:"ami_root_device"`
VolumeRunTags common.TagMap `mapstructure:"run_volume_tags" cty:"run_volume_tags"`
Architecture *string `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture"`
}
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
"decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false},
"insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false},
"mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false},
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
"skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false},
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
"availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false},
"block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false},
"disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false},
"ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false},
"enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false},
"iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false},
"skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false},
"temporary_iam_instance_profile_policy_document": &hcldec.BlockSpec{TypeName: "temporary_iam_instance_profile_policy_document", Nested: hcldec.ObjectSpec((*common.FlatPolicyDocument)(nil).HCL2Spec())},
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
"instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false},
"security_group_filter": &hcldec.BlockSpec{TypeName: "security_group_filter", Nested: hcldec.ObjectSpec((*common.FlatSecurityGroupFilterOptions)(nil).HCL2Spec())},
"run_tags": &hcldec.BlockAttrsSpec{TypeName: "run_tags", ElementType: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_ids": &hcldec.AttrSpec{Name: "security_group_ids", Type: cty.List(cty.String), Required: false},
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
"source_ami_filter": &hcldec.BlockSpec{TypeName: "source_ami_filter", Nested: hcldec.ObjectSpec((*common.FlatAmiFilterOptions)(nil).HCL2Spec())},
"spot_instance_types": &hcldec.AttrSpec{Name: "spot_instance_types", Type: cty.List(cty.String), Required: false},
"spot_price": &hcldec.AttrSpec{Name: "spot_price", Type: cty.String, Required: false},
"spot_price_auto_product": &hcldec.AttrSpec{Name: "spot_price_auto_product", Type: cty.String, Required: false},
"spot_tags": &hcldec.BlockAttrsSpec{TypeName: "spot_tags", ElementType: cty.String, Required: false},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"temporary_security_group_source_cidrs": &hcldec.AttrSpec{Name: "temporary_security_group_source_cidrs", Type: cty.List(cty.String), Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
"user_data_file": &hcldec.AttrSpec{Name: "user_data_file", Type: cty.String, Required: false},
"vpc_filter": &hcldec.BlockSpec{TypeName: "vpc_filter", Nested: hcldec.ObjectSpec((*common.FlatVpcFilterOptions)(nil).HCL2Spec())},
"vpc_id": &hcldec.AttrSpec{Name: "vpc_id", Type: cty.String, Required: false},
"windows_password_timeout": &hcldec.AttrSpec{Name: "windows_password_timeout", Type: cty.String, Required: false},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
"ssh_interface": &hcldec.AttrSpec{Name: "ssh_interface", Type: cty.String, Required: false},
"ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
"ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false},
"ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false},
"ami_users": &hcldec.AttrSpec{Name: "ami_users", Type: cty.List(cty.String), Required: false},
"ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false},
"ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false},
"ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
"force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false},
"encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false},
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"region_kms_key_ids": &hcldec.BlockAttrsSpec{TypeName: "region_kms_key_ids", ElementType: cty.String, Required: false},
"skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false},
"snapshot_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
"snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false},
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
"launch_block_device_mappings": &hcldec.BlockListSpec{TypeName: "launch_block_device_mappings", Nested: hcldec.ObjectSpec((*FlatBlockDevice)(nil).HCL2Spec())},
"ami_root_device": &hcldec.BlockSpec{TypeName: "ami_root_device", Nested: hcldec.ObjectSpec((*FlatRootBlockDevice)(nil).HCL2Spec())},
"run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "run_volume_tags", ElementType: cty.String, Required: false},
"ami_architecture": &hcldec.AttrSpec{Name: "ami_architecture", Type: cty.String, Required: false},
}
return s
}
// FlatRootBlockDevice is an auto-generated flat version of RootBlockDevice.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatRootBlockDevice struct {
SourceDeviceName *string `mapstructure:"source_device_name" cty:"source_device_name"`
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name"`
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination"`
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops"`
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type"`
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size"`
}
// FlatMapstructure returns a new FlatRootBlockDevice.
// FlatRootBlockDevice is an auto-generated flat version of RootBlockDevice.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*RootBlockDevice) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatRootBlockDevice)
}
// HCL2Spec returns the hcl spec of a RootBlockDevice.
// This spec is used by HCL to read the fields of RootBlockDevice.
// The decoded values from this spec will then be applied to a FlatRootBlockDevice.
func (*FlatRootBlockDevice) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"source_device_name": &hcldec.AttrSpec{Name: "source_device_name", Type: cty.String, Required: false},
"device_name": &hcldec.AttrSpec{Name: "device_name", Type: cty.String, Required: false},
"delete_on_termination": &hcldec.AttrSpec{Name: "delete_on_termination", Type: cty.Bool, Required: false},
"iops": &hcldec.AttrSpec{Name: "iops", Type: cty.Number, Required: false},
"volume_type": &hcldec.AttrSpec{Name: "volume_type", Type: cty.String, Required: false},
"volume_size": &hcldec.AttrSpec{Name: "volume_size", Type: cty.Number, Required: false},
}
return s
}

View File

@ -31,7 +31,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) {
"access_key": []string{},
}
warnings, err := b.Prepare(c)
_, warnings, err := b.Prepare(c)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -46,7 +46,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}

View File

@ -1,4 +1,5 @@
//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config,BlockDevice
// The ebsvolume package contains a packer.Builder implementation that builds
// EBS volumes for Amazon EC2 using an ephemeral instance,
@ -10,6 +11,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/hcl/v2/hcldec"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
@ -79,7 +81,9 @@ type EngineVarsTemplate struct {
SourceAMI string
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs = awscommon.TemplateFuncs
// Create passthrough for {{ .BuildRegion }} and {{ .SourceAMI }} variables
// so we can fill them in later
@ -92,7 +96,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
InterpolateContext: &b.config.ctx,
}, raws...)
if err != nil {
return nil, err
return nil, nil, err
}
// Accumulate any errors
@ -129,11 +133,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return warns, errs
return nil, warns, errs
}
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
return warns, nil
return nil, warns, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
@ -227,6 +231,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
},
&awscommon.StepIamInstanceProfile{
IamInstanceProfile: b.config.IamInstanceProfile,
SkipProfileValidation: b.config.SkipProfileValidation,
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
},
instanceStep,

View File

@ -0,0 +1,258 @@
// Code generated by "mapstructure-to-hcl2 -type Config,BlockDevice"; DO NOT EDIT.
package ebsvolume
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/zclconf/go-cty/cty"
)
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatBlockDevice struct {
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination"`
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name"`
Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted"`
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops"`
NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device"`
SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id"`
VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name"`
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type"`
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size"`
KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
Tags common.TagMap `mapstructure:"tags" required:"false" cty:"tags"`
}
// FlatMapstructure returns a new FlatBlockDevice.
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*BlockDevice) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatBlockDevice)
}
// HCL2Spec returns the hcl spec of a BlockDevice.
// This spec is used by HCL to read the fields of BlockDevice.
// The decoded values from this spec will then be applied to a FlatBlockDevice.
func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"delete_on_termination": &hcldec.AttrSpec{Name: "delete_on_termination", Type: cty.Bool, Required: false},
"device_name": &hcldec.AttrSpec{Name: "device_name", Type: cty.String, Required: false},
"encrypted": &hcldec.AttrSpec{Name: "encrypted", Type: cty.Bool, Required: false},
"iops": &hcldec.AttrSpec{Name: "iops", Type: cty.Number, Required: false},
"no_device": &hcldec.AttrSpec{Name: "no_device", Type: cty.Bool, Required: false},
"snapshot_id": &hcldec.AttrSpec{Name: "snapshot_id", Type: cty.String, Required: false},
"virtual_name": &hcldec.AttrSpec{Name: "virtual_name", Type: cty.String, Required: false},
"volume_type": &hcldec.AttrSpec{Name: "volume_type", Type: cty.String, Required: false},
"volume_size": &hcldec.AttrSpec{Name: "volume_size", Type: cty.Number, Required: false},
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
}
return s
}
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key"`
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check"`
Token *string `mapstructure:"token" required:"false" cty:"token"`
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine"`
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address"`
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone"`
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes"`
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter"`
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
VolumeMappings []FlatBlockDevice `mapstructure:"ebs_volumes" required:"false" cty:"ebs_volumes"`
VolumeRunTags common.TagMap `mapstructure:"run_volume_tags" cty:"run_volume_tags"`
}
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
"decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false},
"insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false},
"mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false},
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
"skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false},
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
"availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false},
"block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false},
"disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false},
"ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false},
"enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false},
"iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false},
"skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false},
"temporary_iam_instance_profile_policy_document": &hcldec.BlockSpec{TypeName: "temporary_iam_instance_profile_policy_document", Nested: hcldec.ObjectSpec((*common.FlatPolicyDocument)(nil).HCL2Spec())},
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
"instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false},
"security_group_filter": &hcldec.BlockSpec{TypeName: "security_group_filter", Nested: hcldec.ObjectSpec((*common.FlatSecurityGroupFilterOptions)(nil).HCL2Spec())},
"run_tags": &hcldec.BlockAttrsSpec{TypeName: "run_tags", ElementType: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_ids": &hcldec.AttrSpec{Name: "security_group_ids", Type: cty.List(cty.String), Required: false},
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
"source_ami_filter": &hcldec.BlockSpec{TypeName: "source_ami_filter", Nested: hcldec.ObjectSpec((*common.FlatAmiFilterOptions)(nil).HCL2Spec())},
"spot_instance_types": &hcldec.AttrSpec{Name: "spot_instance_types", Type: cty.List(cty.String), Required: false},
"spot_price": &hcldec.AttrSpec{Name: "spot_price", Type: cty.String, Required: false},
"spot_price_auto_product": &hcldec.AttrSpec{Name: "spot_price_auto_product", Type: cty.String, Required: false},
"spot_tags": &hcldec.BlockAttrsSpec{TypeName: "spot_tags", ElementType: cty.String, Required: false},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"temporary_security_group_source_cidrs": &hcldec.AttrSpec{Name: "temporary_security_group_source_cidrs", Type: cty.List(cty.String), Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
"user_data_file": &hcldec.AttrSpec{Name: "user_data_file", Type: cty.String, Required: false},
"vpc_filter": &hcldec.BlockSpec{TypeName: "vpc_filter", Nested: hcldec.ObjectSpec((*common.FlatVpcFilterOptions)(nil).HCL2Spec())},
"vpc_id": &hcldec.AttrSpec{Name: "vpc_id", Type: cty.String, Required: false},
"windows_password_timeout": &hcldec.AttrSpec{Name: "windows_password_timeout", Type: cty.String, Required: false},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
"ssh_interface": &hcldec.AttrSpec{Name: "ssh_interface", Type: cty.String, Required: false},
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
"ebs_volumes": &hcldec.BlockListSpec{TypeName: "ebs_volumes", Nested: hcldec.ObjectSpec((*FlatBlockDevice)(nil).HCL2Spec())},
"run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "run_volume_tags", ElementType: cty.String, Required: false},
}
return s
}

View File

@ -31,7 +31,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) {
"access_key": []string{},
}
warnings, err := b.Prepare(c)
_, warnings, err := b.Prepare(c)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -46,7 +46,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -62,7 +62,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) {
// Test good
config["shutdown_behavior"] = "terminate"
config["skip_region_validation"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -72,7 +72,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) {
// Test good
config["shutdown_behavior"] = "stop"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -82,7 +82,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) {
// Test bad
config["shutdown_behavior"] = "foobar"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}

View File

@ -1,4 +1,5 @@
//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config
// The instance package contains a packer.Builder implementation that builds
// AMIs for Amazon EC2 backed by instance storage, as opposed to EBS storage.
@ -13,6 +14,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/hcl/v2/hcldec"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
@ -93,7 +95,9 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
configs := make([]interface{}, len(raws)+1)
configs[0] = map[string]interface{}{
"bundle_prefix": "image-{{timestamp}}",
@ -118,7 +122,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
},
}, configs...)
if err != nil {
return nil, err
return nil, nil, err
}
if b.config.PackerConfig.PackerForce {
@ -218,10 +222,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return warns, errs
return nil, warns, errs
}
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
return warns, nil
return nil, warns, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
@ -318,6 +322,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
},
&awscommon.StepIamInstanceProfile{
IamInstanceProfile: b.config.IamInstanceProfile,
SkipProfileValidation: b.config.SkipProfileValidation,
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
},
instanceStep,

View File

@ -0,0 +1,267 @@
// Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT.
package instance
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key"`
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check"`
Token *string `mapstructure:"token" required:"false" cty:"token"`
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine"`
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name"`
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description"`
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type"`
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users"`
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups"`
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes"`
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions"`
AMITags common.TagMap `mapstructure:"tags" required:"false" cty:"tags"`
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
SnapshotTags common.TagMap `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address"`
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone"`
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes"`
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter"`
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"`
LaunchMappings []common.FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings"`
AccountId *string `mapstructure:"account_id" required:"true" cty:"account_id"`
BundleDestination *string `mapstructure:"bundle_destination" required:"false" cty:"bundle_destination"`
BundlePrefix *string `mapstructure:"bundle_prefix" required:"false" cty:"bundle_prefix"`
BundleUploadCommand *string `mapstructure:"bundle_upload_command" required:"false" cty:"bundle_upload_command"`
BundleVolCommand *string `mapstructure:"bundle_vol_command" required:"false" cty:"bundle_vol_command"`
S3Bucket *string `mapstructure:"s3_bucket" required:"true" cty:"s3_bucket"`
X509CertPath *string `mapstructure:"x509_cert_path" required:"true" cty:"x509_cert_path"`
X509KeyPath *string `mapstructure:"x509_key_path" required:"true" cty:"x509_key_path"`
X509UploadPath *string `mapstructure:"x509_upload_path" required:"false" cty:"x509_upload_path"`
}
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
"decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false},
"insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false},
"mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false},
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
"skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false},
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
"ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
"ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false},
"ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false},
"ami_users": &hcldec.AttrSpec{Name: "ami_users", Type: cty.List(cty.String), Required: false},
"ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false},
"ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false},
"ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
"force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false},
"encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false},
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"region_kms_key_ids": &hcldec.BlockAttrsSpec{TypeName: "region_kms_key_ids", ElementType: cty.String, Required: false},
"skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false},
"snapshot_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
"snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false},
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
"availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false},
"block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false},
"disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false},
"ebs_optimized": &hcldec.AttrSpec{Name: "ebs_optimized", Type: cty.Bool, Required: false},
"enable_t2_unlimited": &hcldec.AttrSpec{Name: "enable_t2_unlimited", Type: cty.Bool, Required: false},
"iam_instance_profile": &hcldec.AttrSpec{Name: "iam_instance_profile", Type: cty.String, Required: false},
"skip_profile_validation": &hcldec.AttrSpec{Name: "skip_profile_validation", Type: cty.Bool, Required: false},
"temporary_iam_instance_profile_policy_document": &hcldec.BlockSpec{TypeName: "temporary_iam_instance_profile_policy_document", Nested: hcldec.ObjectSpec((*common.FlatPolicyDocument)(nil).HCL2Spec())},
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
"instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false},
"security_group_filter": &hcldec.BlockSpec{TypeName: "security_group_filter", Nested: hcldec.ObjectSpec((*common.FlatSecurityGroupFilterOptions)(nil).HCL2Spec())},
"run_tags": &hcldec.BlockAttrsSpec{TypeName: "run_tags", ElementType: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_ids": &hcldec.AttrSpec{Name: "security_group_ids", Type: cty.List(cty.String), Required: false},
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
"source_ami_filter": &hcldec.BlockSpec{TypeName: "source_ami_filter", Nested: hcldec.ObjectSpec((*common.FlatAmiFilterOptions)(nil).HCL2Spec())},
"spot_instance_types": &hcldec.AttrSpec{Name: "spot_instance_types", Type: cty.List(cty.String), Required: false},
"spot_price": &hcldec.AttrSpec{Name: "spot_price", Type: cty.String, Required: false},
"spot_price_auto_product": &hcldec.AttrSpec{Name: "spot_price_auto_product", Type: cty.String, Required: false},
"spot_tags": &hcldec.BlockAttrsSpec{TypeName: "spot_tags", ElementType: cty.String, Required: false},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"temporary_security_group_source_cidrs": &hcldec.AttrSpec{Name: "temporary_security_group_source_cidrs", Type: cty.List(cty.String), Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
"user_data_file": &hcldec.AttrSpec{Name: "user_data_file", Type: cty.String, Required: false},
"vpc_filter": &hcldec.BlockSpec{TypeName: "vpc_filter", Nested: hcldec.ObjectSpec((*common.FlatVpcFilterOptions)(nil).HCL2Spec())},
"vpc_id": &hcldec.AttrSpec{Name: "vpc_id", Type: cty.String, Required: false},
"windows_password_timeout": &hcldec.AttrSpec{Name: "windows_password_timeout", Type: cty.String, Required: false},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
"ssh_interface": &hcldec.AttrSpec{Name: "ssh_interface", Type: cty.String, Required: false},
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
"launch_block_device_mappings": &hcldec.BlockListSpec{TypeName: "launch_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
"account_id": &hcldec.AttrSpec{Name: "account_id", Type: cty.String, Required: false},
"bundle_destination": &hcldec.AttrSpec{Name: "bundle_destination", Type: cty.String, Required: false},
"bundle_prefix": &hcldec.AttrSpec{Name: "bundle_prefix", Type: cty.String, Required: false},
"bundle_upload_command": &hcldec.AttrSpec{Name: "bundle_upload_command", Type: cty.String, Required: false},
"bundle_vol_command": &hcldec.AttrSpec{Name: "bundle_vol_command", Type: cty.String, Required: false},
"s3_bucket": &hcldec.AttrSpec{Name: "s3_bucket", Type: cty.String, Required: false},
"x509_cert_path": &hcldec.AttrSpec{Name: "x509_cert_path", Type: cty.String, Required: false},
"x509_key_path": &hcldec.AttrSpec{Name: "x509_key_path", Type: cty.String, Required: false},
"x509_upload_path": &hcldec.AttrSpec{Name: "x509_upload_path", Type: cty.String, Required: false},
}
return s
}

View File

@ -47,7 +47,7 @@ func TestBuilderPrepare_AccountId(t *testing.T) {
defer tempfile.Close()
config["account_id"] = ""
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -56,7 +56,7 @@ func TestBuilderPrepare_AccountId(t *testing.T) {
}
config["account_id"] = "foo"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -65,7 +65,7 @@ func TestBuilderPrepare_AccountId(t *testing.T) {
}
config["account_id"] = "0123-0456-7890"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -87,7 +87,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test good
config["ami_name"] = "foo"
config["skip_region_validation"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -98,7 +98,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
config["ami_name"] = "foo {{"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -109,7 +109,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
delete(config, "ami_name")
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -126,7 +126,7 @@ func TestBuilderPrepare_BundleDestination(t *testing.T) {
defer tempfile.Close()
config["bundle_destination"] = ""
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -146,7 +146,7 @@ func TestBuilderPrepare_BundlePrefix(t *testing.T) {
defer os.Remove(tempfile.Name())
defer tempfile.Close()
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -167,7 +167,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -184,7 +184,7 @@ func TestBuilderPrepare_S3Bucket(t *testing.T) {
defer tempfile.Close()
config["s3_bucket"] = ""
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -193,7 +193,7 @@ func TestBuilderPrepare_S3Bucket(t *testing.T) {
}
config["s3_bucket"] = "foo"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -210,7 +210,7 @@ func TestBuilderPrepare_X509CertPath(t *testing.T) {
defer tempfile.Close()
config["x509_cert_path"] = ""
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -219,7 +219,7 @@ func TestBuilderPrepare_X509CertPath(t *testing.T) {
}
config["x509_cert_path"] = "i/am/a/file/that/doesnt/exist"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -235,7 +235,7 @@ func TestBuilderPrepare_X509CertPath(t *testing.T) {
defer tf.Close()
config["x509_cert_path"] = tf.Name()
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -252,7 +252,7 @@ func TestBuilderPrepare_X509KeyPath(t *testing.T) {
defer tempfile.Close()
config["x509_key_path"] = ""
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -261,7 +261,7 @@ func TestBuilderPrepare_X509KeyPath(t *testing.T) {
}
config["x509_key_path"] = "i/am/a/file/that/doesnt/exist"
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -277,7 +277,7 @@ func TestBuilderPrepare_X509KeyPath(t *testing.T) {
defer tf.Close()
config["x509_key_path"] = tf.Name()
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -294,7 +294,7 @@ func TestBuilderPrepare_X509UploadPath(t *testing.T) {
defer tempfile.Close()
config["x509_upload_path"] = ""
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}

View File

@ -237,7 +237,7 @@ func NewAzureClient(subscriptionID, resourceGroupName, storageAccountName string
azureClient.GalleryImagesClient.RequestInspector = withInspection(maxlen)
azureClient.GalleryImagesClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.GalleryImagesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.GalleryImagesClient.UserAgent)
azureClient.GalleryImageVersionsClient.Client.PollingDuration = PollingDuration
azureClient.GalleryImagesClient.Client.PollingDuration = PollingDuration
keyVaultURL, err := url.Parse(cloud.KeyVaultEndpoint)
if err != nil {

View File

@ -14,6 +14,7 @@ import (
"github.com/Azure/azure-sdk-for-go/storage"
"github.com/Azure/go-autorest/autorest/adal"
"github.com/dgrijalva/jwt-go"
"github.com/hashicorp/hcl/v2/hcldec"
packerAzureCommon "github.com/hashicorp/packer/builder/azure/common"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/builder/azure/common/lin"
@ -24,7 +25,7 @@ import (
)
type Builder struct {
config *Config
config Config
stateBag multistep.StateBag
runner multistep.Runner
}
@ -34,20 +35,20 @@ const (
DefaultSecretName = "packerKeyVaultSecret"
)
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
c, warnings, errs := newConfig(raws...)
if errs != nil {
return warnings, errs
}
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
b.config = c
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
warnings, errs := b.config.Prepare(raws...)
if errs != nil {
return nil, warnings, errs
}
b.stateBag = new(multistep.BasicStateBag)
b.configureStateBag(b.stateBag)
b.setTemplateParameters(b.stateBag)
b.setImageParameters(b.stateBag)
return warnings, errs
return nil, warnings, errs
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
@ -64,7 +65,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
log.Print(":: Configuration")
packerAzureCommon.DumpConfig(b.config, func(s string) { log.Print(s) })
packerAzureCommon.DumpConfig(&b.config, func(s string) { log.Print(s) })
b.stateBag.Put("hook", hook)
b.stateBag.Put(constants.Ui, ui)
@ -90,7 +91,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
resolver := newResourceResolver(azureClient)
if err := resolver.Resolve(b.config); err != nil {
if err := resolver.Resolve(&b.config); err != nil {
return nil, err
}
if b.config.ClientConfig.ObjectID == "" {
@ -197,8 +198,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
if b.config.OSType == constants.Target_Linux {
steps = []multistep.Step{
NewStepCreateResourceGroup(azureClient, ui),
NewStepValidateTemplate(azureClient, ui, b.config, GetVirtualMachineDeployment),
NewStepDeployTemplate(azureClient, ui, b.config, deploymentName, GetVirtualMachineDeployment),
NewStepValidateTemplate(azureClient, ui, &b.config, GetVirtualMachineDeployment),
NewStepDeployTemplate(azureClient, ui, &b.config, deploymentName, GetVirtualMachineDeployment),
NewStepGetIPAddress(azureClient, ui, endpointConnectType),
&communicator.StepConnectSSH{
Config: &b.config.Comm,
@ -212,10 +213,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
NewStepGetOSDisk(azureClient, ui),
NewStepGetAdditionalDisks(azureClient, ui),
NewStepPowerOffCompute(azureClient, ui),
NewStepSnapshotOSDisk(azureClient, ui, b.config),
NewStepSnapshotDataDisks(azureClient, ui, b.config),
NewStepSnapshotOSDisk(azureClient, ui, &b.config),
NewStepSnapshotDataDisks(azureClient, ui, &b.config),
NewStepCaptureImage(azureClient, ui),
NewStepPublishToSharedImageGallery(azureClient, ui, b.config),
NewStepPublishToSharedImageGallery(azureClient, ui, &b.config),
NewStepDeleteResourceGroup(azureClient, ui),
NewStepDeleteOSDisk(azureClient, ui),
NewStepDeleteAdditionalDisks(azureClient, ui),
@ -224,17 +225,13 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
keyVaultDeploymentName := b.stateBag.Get(constants.ArmKeyVaultDeploymentName).(string)
steps = []multistep.Step{
NewStepCreateResourceGroup(azureClient, ui),
NewStepValidateTemplate(azureClient, ui, b.config, GetKeyVaultDeployment),
NewStepDeployTemplate(azureClient, ui, b.config, keyVaultDeploymentName, GetKeyVaultDeployment),
NewStepValidateTemplate(azureClient, ui, &b.config, GetKeyVaultDeployment),
NewStepDeployTemplate(azureClient, ui, &b.config, keyVaultDeploymentName, GetKeyVaultDeployment),
NewStepGetCertificate(azureClient, ui),
NewStepSetCertificate(b.config, ui),
NewStepValidateTemplate(azureClient, ui, b.config, GetVirtualMachineDeployment),
NewStepDeployTemplate(azureClient, ui, b.config, deploymentName, GetVirtualMachineDeployment),
NewStepSetCertificate(&b.config, ui),
NewStepValidateTemplate(azureClient, ui, &b.config, GetVirtualMachineDeployment),
NewStepDeployTemplate(azureClient, ui, &b.config, deploymentName, GetVirtualMachineDeployment),
NewStepGetIPAddress(azureClient, ui, endpointConnectType),
&StepSaveWinRMPassword{
Password: b.config.tmpAdminPassword,
BuildName: b.config.PackerBuildName,
},
&communicator.StepConnectWinRM{
Config: &b.config.Comm,
Host: func(stateBag multistep.StateBag) (string, error) {
@ -251,10 +248,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
NewStepGetOSDisk(azureClient, ui),
NewStepGetAdditionalDisks(azureClient, ui),
NewStepPowerOffCompute(azureClient, ui),
NewStepSnapshotOSDisk(azureClient, ui, b.config),
NewStepSnapshotDataDisks(azureClient, ui, b.config),
NewStepSnapshotOSDisk(azureClient, ui, &b.config),
NewStepSnapshotDataDisks(azureClient, ui, &b.config),
NewStepCaptureImage(azureClient, ui),
NewStepPublishToSharedImageGallery(azureClient, ui, b.config),
NewStepPublishToSharedImageGallery(azureClient, ui, &b.config),
NewStepDeleteResourceGroup(azureClient, ui),
NewStepDeleteOSDisk(azureClient, ui),
NewStepDeleteAdditionalDisks(azureClient, ui),
@ -398,6 +395,9 @@ func (b *Builder) configureStateBag(stateBag multistep.StateBag) {
stateBag.Put(constants.ArmManagedImageSharedGalleryImageName, b.config.SharedGalleryDestination.SigDestinationImageName)
stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersion, b.config.SharedGalleryDestination.SigDestinationImageVersion)
stateBag.Put(constants.ArmManagedImageSubscription, b.config.ClientConfig.SubscriptionID)
stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersionEndOfLifeDate, b.config.SharedGalleryImageVersionEndOfLifeDate)
stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersionReplicaCount, b.config.SharedGalleryImageVersionReplicaCount)
stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersionExcludeFromLatest, b.config.SharedGalleryImageVersionExcludeFromLatest)
}
}

View File

@ -7,8 +7,8 @@ import (
)
func TestStateBagShouldBePopulatedExpectedValues(t *testing.T) {
var testSubject = &Builder{}
_, err := testSubject.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
var testSubject Builder
_, _, err := testSubject.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
if err != nil {
t.Fatalf("failed to prepare: %s", err)
}

View File

@ -27,7 +27,6 @@ import (
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/builder/azure/pkcs12"
"github.com/hashicorp/packer/common"
commonhelper "github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
@ -120,8 +119,6 @@ type Config struct {
//
// Following is an example.
//
// <!-- -->
//
// "shared_image_gallery_destination": {
// "resource_group": "ResourceGroup",
// "gallery_name": "GalleryName",
@ -140,6 +137,16 @@ type Config struct {
// its default of "60m" (valid time units include `s` for seconds, `m` for
// minutes, and `h` for hours.)
SharedGalleryTimeout time.Duration `mapstructure:"shared_image_gallery_timeout"`
// The end of life date (2006-01-02T15:04:05.99Z) of the gallery Image Version. This property
// can be used for decommissioning purposes.
SharedGalleryImageVersionEndOfLifeDate string `mapstructure:"shared_gallery_image_version_end_of_life_date" required:"false"`
// The number of replicas of the Image Version to be created per region. This
// property would take effect for a region when regionalReplicaCount is not specified.
// Replica count must be between 1 and 10.
SharedGalleryImageVersionReplicaCount int32 `mapstructure:"shared_image_gallery_replica_count" required:"false"`
// If set to true, Virtual Machines deployed from the latest version of the
// Image Definition won't use this Image Version.
SharedGalleryImageVersionExcludeFromLatest bool `mapstructure:"shared_gallery_image_version_exclude_from_latest" required:"false"`
// PublisherName for your base image. See
// [documentation](https://azure.microsoft.com/en-us/documentation/articles/resource-groups-vm-searching/)
// for details.
@ -495,58 +502,57 @@ func (c *Config) createCertificate() (string, error) {
return base64.StdEncoding.EncodeToString(bytes), nil
}
func newConfig(raws ...interface{}) (*Config, []string, error) {
var c Config
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
c.ctx.Funcs = azcommon.TemplateFuncs
err := config.Decode(&c, &config.DecodeOpts{
err := config.Decode(c, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &c.ctx,
}, raws...)
if err != nil {
return nil, nil, err
return nil, err
}
provideDefaultValues(&c)
setRuntimeValues(&c)
setUserNamePassword(&c)
provideDefaultValues(c)
setRuntimeValues(c)
setUserNamePassword(c)
err = c.ClientConfig.SetDefaultValues()
if err != nil {
return nil, nil, err
return nil, err
}
err = setCustomData(&c)
err = setCustomData(c)
if err != nil {
return nil, nil, err
return nil, err
}
// NOTE: if the user did not specify a communicator, then default to both
// SSH and WinRM. This is for backwards compatibility because the code did
// not specifically force the user to set a communicator.
if c.Comm.Type == "" || strings.EqualFold(c.Comm.Type, "ssh") {
err = setSshValues(&c)
err = setSshValues(c)
if err != nil {
return nil, nil, err
return nil, err
}
}
if c.Comm.Type == "" || strings.EqualFold(c.Comm.Type, "winrm") {
err = setWinRMCertificate(&c)
err = setWinRMCertificate(c)
if err != nil {
return nil, nil, err
return nil, err
}
}
var errs *packer.MultiError
errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...)
assertRequiredParametersSet(&c, errs)
assertTagProperties(&c, errs)
assertRequiredParametersSet(c, errs)
assertTagProperties(c, errs)
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
return nil, errs
}
return &c, nil, nil
return nil, nil
}
func setSshValues(c *Config) error {
@ -601,7 +607,6 @@ func setRuntimeValues(c *Config) {
c.tmpAdminPassword = tempName.AdminPassword
// store so that we can access this later during provisioning
commonhelper.SetSharedState("winrm_password", c.tmpAdminPassword, c.PackerConfig.PackerBuildName)
packer.LogSecretFilter.Set(c.tmpAdminPassword)
c.tmpCertificatePassword = tempName.CertificatePassword

View File

@ -9,138 +9,147 @@ import (
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
CloudEnvironmentName *string `mapstructure:"cloud_environment_name" required:"false" cty:"cloud_environment_name"`
ClientID *string `mapstructure:"client_id" cty:"client_id"`
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret"`
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path"`
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt"`
ObjectID *string `mapstructure:"object_id" cty:"object_id"`
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id"`
SubscriptionID *string `mapstructure:"subscription_id" cty:"subscription_id"`
CaptureNamePrefix *string `mapstructure:"capture_name_prefix" cty:"capture_name_prefix"`
CaptureContainerName *string `mapstructure:"capture_container_name" cty:"capture_container_name"`
SharedGallery *FlatSharedImageGallery `mapstructure:"shared_image_gallery" required:"false" cty:"shared_image_gallery"`
SharedGalleryDestination *FlatSharedImageGalleryDestination `mapstructure:"shared_image_gallery_destination" cty:"shared_image_gallery_destination"`
SharedGalleryTimeout *string `mapstructure:"shared_image_gallery_timeout" cty:"shared_image_gallery_timeout"`
ImagePublisher *string `mapstructure:"image_publisher" required:"true" cty:"image_publisher"`
ImageOffer *string `mapstructure:"image_offer" required:"true" cty:"image_offer"`
ImageSku *string `mapstructure:"image_sku" required:"true" cty:"image_sku"`
ImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version"`
ImageUrl *string `mapstructure:"image_url" required:"false" cty:"image_url"`
CustomManagedImageResourceGroupName *string `mapstructure:"custom_managed_image_resource_group_name" required:"false" cty:"custom_managed_image_resource_group_name"`
CustomManagedImageName *string `mapstructure:"custom_managed_image_name" required:"false" cty:"custom_managed_image_name"`
Location *string `mapstructure:"location" cty:"location"`
VMSize *string `mapstructure:"vm_size" required:"false" cty:"vm_size"`
ManagedImageResourceGroupName *string `mapstructure:"managed_image_resource_group_name" cty:"managed_image_resource_group_name"`
ManagedImageName *string `mapstructure:"managed_image_name" cty:"managed_image_name"`
ManagedImageStorageAccountType *string `mapstructure:"managed_image_storage_account_type" required:"false" cty:"managed_image_storage_account_type"`
ManagedImageOSDiskSnapshotName *string `mapstructure:"managed_image_os_disk_snapshot_name" required:"false" cty:"managed_image_os_disk_snapshot_name"`
ManagedImageDataDiskSnapshotPrefix *string `mapstructure:"managed_image_data_disk_snapshot_prefix" required:"false" cty:"managed_image_data_disk_snapshot_prefix"`
ManagedImageZoneResilient *bool `mapstructure:"managed_image_zone_resilient" required:"false" cty:"managed_image_zone_resilient"`
AzureTags map[string]*string `mapstructure:"azure_tags" required:"false" cty:"azure_tags"`
ResourceGroupName *string `mapstructure:"resource_group_name" cty:"resource_group_name"`
StorageAccount *string `mapstructure:"storage_account" cty:"storage_account"`
TempComputeName *string `mapstructure:"temp_compute_name" required:"false" cty:"temp_compute_name"`
TempResourceGroupName *string `mapstructure:"temp_resource_group_name" cty:"temp_resource_group_name"`
BuildResourceGroupName *string `mapstructure:"build_resource_group_name" cty:"build_resource_group_name"`
PrivateVirtualNetworkWithPublicIp *bool `mapstructure:"private_virtual_network_with_public_ip" required:"false" cty:"private_virtual_network_with_public_ip"`
VirtualNetworkName *string `mapstructure:"virtual_network_name" required:"false" cty:"virtual_network_name"`
VirtualNetworkSubnetName *string `mapstructure:"virtual_network_subnet_name" required:"false" cty:"virtual_network_subnet_name"`
VirtualNetworkResourceGroupName *string `mapstructure:"virtual_network_resource_group_name" required:"false" cty:"virtual_network_resource_group_name"`
CustomDataFile *string `mapstructure:"custom_data_file" required:"false" cty:"custom_data_file"`
PlanInfo *FlatPlanInformation `mapstructure:"plan_info" required:"false" cty:"plan_info"`
PollingDurationTimeout *string `mapstructure:"polling_duration_timeout" required:"false" cty:"polling_duration_timeout"`
OSType *string `mapstructure:"os_type" required:"false" cty:"os_type"`
OSDiskSizeGB *int32 `mapstructure:"os_disk_size_gb" required:"false" cty:"os_disk_size_gb"`
AdditionalDiskSize []int32 `mapstructure:"disk_additional_size" required:"false" cty:"disk_additional_size"`
DiskCachingType *string `mapstructure:"disk_caching_type" required:"false" cty:"disk_caching_type"`
AllowedInboundIpAddresses []string `mapstructure:"allowed_inbound_ip_addresses" cty:"allowed_inbound_ip_addresses"`
UserName *string `cty:"user_name"`
Password *string `cty:"password"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" cty:"temporary_key_pair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
AsyncResourceGroupDelete *bool `mapstructure:"async_resourcegroup_delete" required:"false" cty:"async_resourcegroup_delete"`
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
CloudEnvironmentName *string `mapstructure:"cloud_environment_name" required:"false" cty:"cloud_environment_name"`
ClientID *string `mapstructure:"client_id" cty:"client_id"`
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret"`
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path"`
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt"`
ObjectID *string `mapstructure:"object_id" cty:"object_id"`
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id"`
SubscriptionID *string `mapstructure:"subscription_id" cty:"subscription_id"`
CaptureNamePrefix *string `mapstructure:"capture_name_prefix" cty:"capture_name_prefix"`
CaptureContainerName *string `mapstructure:"capture_container_name" cty:"capture_container_name"`
SharedGallery *FlatSharedImageGallery `mapstructure:"shared_image_gallery" required:"false" cty:"shared_image_gallery"`
SharedGalleryDestination *FlatSharedImageGalleryDestination `mapstructure:"shared_image_gallery_destination" cty:"shared_image_gallery_destination"`
SharedGalleryTimeout *string `mapstructure:"shared_image_gallery_timeout" cty:"shared_image_gallery_timeout"`
SharedGalleryImageVersionEndOfLifeDate *string `mapstructure:"shared_gallery_image_version_end_of_life_date" required:"false" cty:"shared_gallery_image_version_end_of_life_date"`
SharedGalleryImageVersionReplicaCount *int32 `mapstructure:"shared_image_gallery_replica_count" required:"false" cty:"shared_image_gallery_replica_count"`
SharedGalleryImageVersionExcludeFromLatest *bool `mapstructure:"shared_gallery_image_version_exclude_from_latest" required:"false" cty:"shared_gallery_image_version_exclude_from_latest"`
ImagePublisher *string `mapstructure:"image_publisher" required:"true" cty:"image_publisher"`
ImageOffer *string `mapstructure:"image_offer" required:"true" cty:"image_offer"`
ImageSku *string `mapstructure:"image_sku" required:"true" cty:"image_sku"`
ImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version"`
ImageUrl *string `mapstructure:"image_url" required:"false" cty:"image_url"`
CustomManagedImageResourceGroupName *string `mapstructure:"custom_managed_image_resource_group_name" required:"false" cty:"custom_managed_image_resource_group_name"`
CustomManagedImageName *string `mapstructure:"custom_managed_image_name" required:"false" cty:"custom_managed_image_name"`
Location *string `mapstructure:"location" cty:"location"`
VMSize *string `mapstructure:"vm_size" required:"false" cty:"vm_size"`
ManagedImageResourceGroupName *string `mapstructure:"managed_image_resource_group_name" cty:"managed_image_resource_group_name"`
ManagedImageName *string `mapstructure:"managed_image_name" cty:"managed_image_name"`
ManagedImageStorageAccountType *string `mapstructure:"managed_image_storage_account_type" required:"false" cty:"managed_image_storage_account_type"`
ManagedImageOSDiskSnapshotName *string `mapstructure:"managed_image_os_disk_snapshot_name" required:"false" cty:"managed_image_os_disk_snapshot_name"`
ManagedImageDataDiskSnapshotPrefix *string `mapstructure:"managed_image_data_disk_snapshot_prefix" required:"false" cty:"managed_image_data_disk_snapshot_prefix"`
ManagedImageZoneResilient *bool `mapstructure:"managed_image_zone_resilient" required:"false" cty:"managed_image_zone_resilient"`
AzureTags map[string]*string `mapstructure:"azure_tags" required:"false" cty:"azure_tags"`
ResourceGroupName *string `mapstructure:"resource_group_name" cty:"resource_group_name"`
StorageAccount *string `mapstructure:"storage_account" cty:"storage_account"`
TempComputeName *string `mapstructure:"temp_compute_name" required:"false" cty:"temp_compute_name"`
TempResourceGroupName *string `mapstructure:"temp_resource_group_name" cty:"temp_resource_group_name"`
BuildResourceGroupName *string `mapstructure:"build_resource_group_name" cty:"build_resource_group_name"`
PrivateVirtualNetworkWithPublicIp *bool `mapstructure:"private_virtual_network_with_public_ip" required:"false" cty:"private_virtual_network_with_public_ip"`
VirtualNetworkName *string `mapstructure:"virtual_network_name" required:"false" cty:"virtual_network_name"`
VirtualNetworkSubnetName *string `mapstructure:"virtual_network_subnet_name" required:"false" cty:"virtual_network_subnet_name"`
VirtualNetworkResourceGroupName *string `mapstructure:"virtual_network_resource_group_name" required:"false" cty:"virtual_network_resource_group_name"`
CustomDataFile *string `mapstructure:"custom_data_file" required:"false" cty:"custom_data_file"`
PlanInfo *FlatPlanInformation `mapstructure:"plan_info" required:"false" cty:"plan_info"`
PollingDurationTimeout *string `mapstructure:"polling_duration_timeout" required:"false" cty:"polling_duration_timeout"`
OSType *string `mapstructure:"os_type" required:"false" cty:"os_type"`
OSDiskSizeGB *int32 `mapstructure:"os_disk_size_gb" required:"false" cty:"os_disk_size_gb"`
AdditionalDiskSize []int32 `mapstructure:"disk_additional_size" required:"false" cty:"disk_additional_size"`
DiskCachingType *string `mapstructure:"disk_caching_type" required:"false" cty:"disk_caching_type"`
AllowedInboundIpAddresses []string `mapstructure:"allowed_inbound_ip_addresses" cty:"allowed_inbound_ip_addresses"`
UserName *string `cty:"user_name"`
Password *string `cty:"password"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" cty:"temporary_key_pair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
AsyncResourceGroupDelete *bool `mapstructure:"async_resourcegroup_delete" required:"false" cty:"async_resourcegroup_delete"`
}
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"cloud_environment_name": &hcldec.AttrSpec{Name: "cloud_environment_name", Type: cty.String, Required: false},
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
"subscription_id": &hcldec.AttrSpec{Name: "subscription_id", Type: cty.String, Required: false},
"capture_name_prefix": &hcldec.AttrSpec{Name: "capture_name_prefix", Type: cty.String, Required: false},
"capture_container_name": &hcldec.AttrSpec{Name: "capture_container_name", Type: cty.String, Required: false},
"shared_image_gallery": &hcldec.BlockSpec{TypeName: "shared_image_gallery", Nested: hcldec.ObjectSpec((*FlatSharedImageGallery)(nil).HCL2Spec())},
"shared_image_gallery_destination": &hcldec.BlockSpec{TypeName: "shared_image_gallery_destination", Nested: hcldec.ObjectSpec((*FlatSharedImageGalleryDestination)(nil).HCL2Spec())},
"shared_image_gallery_timeout": &hcldec.AttrSpec{Name: "shared_image_gallery_timeout", Type: cty.String, Required: false},
"image_publisher": &hcldec.AttrSpec{Name: "image_publisher", Type: cty.String, Required: false},
"image_offer": &hcldec.AttrSpec{Name: "image_offer", Type: cty.String, Required: false},
"image_sku": &hcldec.AttrSpec{Name: "image_sku", Type: cty.String, Required: false},
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
"image_url": &hcldec.AttrSpec{Name: "image_url", Type: cty.String, Required: false},
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"cloud_environment_name": &hcldec.AttrSpec{Name: "cloud_environment_name", Type: cty.String, Required: false},
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
"subscription_id": &hcldec.AttrSpec{Name: "subscription_id", Type: cty.String, Required: false},
"capture_name_prefix": &hcldec.AttrSpec{Name: "capture_name_prefix", Type: cty.String, Required: false},
"capture_container_name": &hcldec.AttrSpec{Name: "capture_container_name", Type: cty.String, Required: false},
"shared_image_gallery": &hcldec.BlockSpec{TypeName: "shared_image_gallery", Nested: hcldec.ObjectSpec((*FlatSharedImageGallery)(nil).HCL2Spec())},
"shared_image_gallery_destination": &hcldec.BlockSpec{TypeName: "shared_image_gallery_destination", Nested: hcldec.ObjectSpec((*FlatSharedImageGalleryDestination)(nil).HCL2Spec())},
"shared_image_gallery_timeout": &hcldec.AttrSpec{Name: "shared_image_gallery_timeout", Type: cty.String, Required: false},
"shared_gallery_image_version_end_of_life_date": &hcldec.AttrSpec{Name: "shared_gallery_image_version_end_of_life_date", Type: cty.String, Required: false},
"shared_image_gallery_replica_count": &hcldec.AttrSpec{Name: "shared_image_gallery_replica_count", Type: cty.Number, Required: false},
"shared_gallery_image_version_exclude_from_latest": &hcldec.AttrSpec{Name: "shared_gallery_image_version_exclude_from_latest", Type: cty.Bool, Required: false},
"image_publisher": &hcldec.AttrSpec{Name: "image_publisher", Type: cty.String, Required: false},
"image_offer": &hcldec.AttrSpec{Name: "image_offer", Type: cty.String, Required: false},
"image_sku": &hcldec.AttrSpec{Name: "image_sku", Type: cty.String, Required: false},
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
"image_url": &hcldec.AttrSpec{Name: "image_url", Type: cty.String, Required: false},
"custom_managed_image_resource_group_name": &hcldec.AttrSpec{Name: "custom_managed_image_resource_group_name", Type: cty.String, Required: false},
"custom_managed_image_name": &hcldec.AttrSpec{Name: "custom_managed_image_name", Type: cty.String, Required: false},
"location": &hcldec.AttrSpec{Name: "location", Type: cty.String, Required: false},
@ -228,10 +237,13 @@ type FlatPlanInformation struct {
// FlatMapstructure returns a new FlatPlanInformation.
// FlatPlanInformation is an auto-generated flat version of PlanInformation.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*PlanInformation) FlatMapstructure() interface{} { return new(FlatPlanInformation) }
func (*PlanInformation) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatPlanInformation)
}
// HCL2Spec returns the hcldec.Spec of a FlatPlanInformation.
// This spec is used by HCL to read the fields of FlatPlanInformation.
// HCL2Spec returns the hcl spec of a PlanInformation.
// This spec is used by HCL to read the fields of PlanInformation.
// The decoded values from this spec will then be applied to a FlatPlanInformation.
func (*FlatPlanInformation) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"plan_name": &hcldec.AttrSpec{Name: "plan_name", Type: cty.String, Required: false},
@ -255,10 +267,13 @@ type FlatSharedImageGallery struct {
// FlatMapstructure returns a new FlatSharedImageGallery.
// FlatSharedImageGallery is an auto-generated flat version of SharedImageGallery.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*SharedImageGallery) FlatMapstructure() interface{} { return new(FlatSharedImageGallery) }
func (*SharedImageGallery) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatSharedImageGallery)
}
// HCL2Spec returns the hcldec.Spec of a FlatSharedImageGallery.
// This spec is used by HCL to read the fields of FlatSharedImageGallery.
// HCL2Spec returns the hcl spec of a SharedImageGallery.
// This spec is used by HCL to read the fields of SharedImageGallery.
// The decoded values from this spec will then be applied to a FlatSharedImageGallery.
func (*FlatSharedImageGallery) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"subscription": &hcldec.AttrSpec{Name: "subscription", Type: cty.String, Required: false},
@ -283,12 +298,13 @@ type FlatSharedImageGalleryDestination struct {
// FlatMapstructure returns a new FlatSharedImageGalleryDestination.
// FlatSharedImageGalleryDestination is an auto-generated flat version of SharedImageGalleryDestination.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*SharedImageGalleryDestination) FlatMapstructure() interface{} {
func (*SharedImageGalleryDestination) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatSharedImageGalleryDestination)
}
// HCL2Spec returns the hcldec.Spec of a FlatSharedImageGalleryDestination.
// This spec is used by HCL to read the fields of FlatSharedImageGalleryDestination.
// HCL2Spec returns the hcl spec of a SharedImageGalleryDestination.
// This spec is used by HCL to read the fields of SharedImageGalleryDestination.
// The decoded values from this spec will then be applied to a FlatSharedImageGalleryDestination.
func (*FlatSharedImageGalleryDestination) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"resource_group": &hcldec.AttrSpec{Name: "resource_group", Type: cty.String, Required: false},

View File

@ -26,7 +26,8 @@ var requiredConfigValues = []string{
}
func TestConfigShouldProvideReasonableDefaultValues(t *testing.T) {
c, _, err := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
_, err := c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
if err != nil {
t.Error("Expected configuration creation to succeed, but it failed!\n")
@ -63,7 +64,8 @@ func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) {
builderValues["managed_image_storage_account_type"] = "Premium_LRS"
builderValues["disk_caching_type"] = "None"
c, _, err := newConfig(builderValues, getPackerConfiguration())
var c Config
_, err := c.Prepare(builderValues, getPackerConfiguration())
if err != nil {
t.Fatalf("newConfig failed: %s", err)
@ -99,7 +101,8 @@ func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) {
}
func TestConfigShouldDefaultVMSizeToStandardA1(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
if c.VMSize != "Standard_A1" {
t.Errorf("Expected 'VMSize' to default to 'Standard_A1', but got '%s'.", c.VMSize)
@ -107,7 +110,8 @@ func TestConfigShouldDefaultVMSizeToStandardA1(t *testing.T) {
}
func TestConfigShouldDefaultImageVersionToLatest(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
if c.ImageVersion != "latest" {
t.Errorf("Expected 'ImageVersion' to default to 'latest', but got '%s'.", c.ImageVersion)
@ -127,7 +131,8 @@ func TestConfigShouldNotDefaultImageVersionIfCustomImage(t *testing.T) {
"communicator": "none",
}
c, _, _ := newConfig(config, getPackerConfiguration())
var c Config
c.Prepare(config, getPackerConfiguration())
if c.ImageVersion != "" {
t.Errorf("Expected 'ImageVersion' to empty, but got '%s'.", c.ImageVersion)
}
@ -153,7 +158,8 @@ func TestConfigShouldNormalizeOSTypeCase(t *testing.T) {
for k, v := range os_types {
for _, os_type := range v {
config["os_type"] = os_type
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatalf("Expected config to accept the value %q, but it did not", os_type)
}
@ -167,7 +173,8 @@ func TestConfigShouldNormalizeOSTypeCase(t *testing.T) {
bad_os_types := []string{"", "does-not-exist"}
for _, os_type := range bad_os_types {
config["os_type"] = os_type
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatalf("Expected config to not accept the value %q, but it did", os_type)
}
@ -191,7 +198,8 @@ func TestConfigShouldRejectCustomImageAndMarketPlace(t *testing.T) {
for _, x := range marketPlace {
config[x] = "ignore"
_, _, err := newConfig(config, packerConfiguration)
var c Config
_, err := c.Prepare(config, packerConfiguration)
if err == nil {
t.Errorf("Expected Config to reject image_url and %s, but it did not", x)
}
@ -212,7 +220,8 @@ func TestConfigVirtualNetworkNameIsOptional(t *testing.T) {
"virtual_network_name": "MyVirtualNetwork",
}
c, _, _ := newConfig(config, getPackerConfiguration())
var c Config
c.Prepare(config, getPackerConfiguration())
if c.VirtualNetworkName != "MyVirtualNetwork" {
t.Errorf("Expected Config to set virtual_network_name to MyVirtualNetwork, but got %q", c.VirtualNetworkName)
}
@ -241,7 +250,8 @@ func TestConfigVirtualNetworkResourceGroupNameMustBeSetWithVirtualNetworkName(t
"virtual_network_resource_group_name": "MyVirtualNetworkRG",
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Error("Expected Config to reject virtual_network_resource_group_name, if virtual_network_name is not set.")
}
@ -264,7 +274,8 @@ func TestConfigVirtualNetworkSubnetNameMustBeSetWithVirtualNetworkName(t *testin
"virtual_network_subnet_name": "MyVirtualNetworkRG",
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Error("Expected Config to reject virtual_network_subnet_name, if virtual_network_name is not set.")
}
@ -284,7 +295,8 @@ func TestConfigAllowedInboundIpAddressesIsOptional(t *testing.T) {
"virtual_network_name": "MyVirtualNetwork",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
@ -311,7 +323,8 @@ func TestConfigShouldAcceptCorrectInboundIpAddresses(t *testing.T) {
}
config["allowed_inbound_ip_addresses"] = ipValue0
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
@ -321,7 +334,7 @@ func TestConfigShouldAcceptCorrectInboundIpAddresses(t *testing.T) {
}
config["allowed_inbound_ip_addresses"] = cidrValue2
c, _, err = newConfig(config, getPackerConfiguration())
_, err = c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
@ -331,7 +344,7 @@ func TestConfigShouldAcceptCorrectInboundIpAddresses(t *testing.T) {
}
config["allowed_inbound_ip_addresses"] = []string{ipValue0, cidrValue2, ipValue1, cidrValue3}
c, _, err = newConfig(config, getPackerConfiguration())
_, err = c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
@ -357,13 +370,14 @@ func TestConfigShouldRejectIncorrectInboundIpAddresses(t *testing.T) {
}
config["allowed_inbound_ip_addresses"] = []string{"127.0.0.1", "127.0.0.two"}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Errorf("Expected configuration creation to fail, but it succeeded with the malformed allowed_inbound_ip_addresses set to %v", c.AllowedInboundIpAddresses)
}
config["allowed_inbound_ip_addresses"] = []string{"192.168.100.1000/24", "10.10.1.16/32"}
c, _, err = newConfig(config, getPackerConfiguration())
_, err = c.Prepare(config, getPackerConfiguration())
if err == nil {
// 192.168.100.1000/24 is invalid
t.Errorf("Expected configuration creation to fail, but it succeeded with the malformed allowed_inbound_ip_addresses set to %v", c.AllowedInboundIpAddresses)
@ -384,20 +398,22 @@ func TestConfigShouldRejectInboundIpAddressesWithVirtualNetwork(t *testing.T) {
"allowed_inbound_ip_addresses": "127.0.0.1",
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
config["virtual_network_name"] = "some_vnet_name"
_, _, err = newConfig(config, getPackerConfiguration())
_, err = c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Errorf("Expected configuration creation to fail, but it succeeded with allowed_inbound_ip_addresses and virtual_network_name both specified")
}
}
func TestConfigShouldDefaultToPublicCloud(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
if c.ClientConfig.CloudEnvironmentName != "Public" {
t.Errorf("Expected 'CloudEnvironmentName' to default to 'Public', but got '%s'.", c.ClientConfig.CloudEnvironmentName)
@ -448,7 +464,8 @@ func TestConfigInstantiatesCorrectAzureEnvironment(t *testing.T) {
for _, x := range table {
config["cloud_environment_name"] = x.name
c, _, err := newConfig(config, packerConfiguration)
var c Config
_, err := c.Prepare(config, packerConfiguration)
if err != nil {
t.Fatal(err)
}
@ -463,7 +480,8 @@ func TestUserShouldProvideRequiredValues(t *testing.T) {
builderValues := getArmBuilderConfiguration()
// Ensure we can successfully create a config.
_, _, err := newConfig(builderValues, getPackerConfiguration())
var c Config
_, err := c.Prepare(builderValues, getPackerConfiguration())
if err != nil {
t.Error("Expected configuration creation to succeed, but it failed!\n")
t.Fatalf(" -> %+v\n", builderValues)
@ -474,7 +492,8 @@ func TestUserShouldProvideRequiredValues(t *testing.T) {
originalValue := builderValues[v]
delete(builderValues, v)
_, _, err := newConfig(builderValues, getPackerConfiguration())
var c Config
_, err := c.Prepare(builderValues, getPackerConfiguration())
if err == nil {
t.Error("Expected configuration creation to fail, but it succeeded!\n")
t.Fatalf(" -> %+v\n", builderValues)
@ -485,7 +504,8 @@ func TestUserShouldProvideRequiredValues(t *testing.T) {
}
func TestSystemShouldDefineRuntimeValues(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
if c.Password == "" {
t.Errorf("Expected Password to not be empty, but it was '%s'!", c.Password)
@ -513,7 +533,8 @@ func TestSystemShouldDefineRuntimeValues(t *testing.T) {
}
func TestConfigShouldTransformToVirtualMachineCaptureParameters(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
parameters := c.toVirtualMachineCaptureParameters()
if *parameters.DestinationContainerName != c.CaptureContainerName {
@ -530,7 +551,8 @@ func TestConfigShouldTransformToVirtualMachineCaptureParameters(t *testing.T) {
}
func TestConfigShouldSupportPackersConfigElements(t *testing.T) {
c, _, err := newConfig(
var c Config
_, err := c.Prepare(
getArmBuilderConfiguration(),
getPackerConfiguration(),
getPackerCommunicatorConfiguration())
@ -554,7 +576,8 @@ func TestWinRMConfigShouldSetRoundTripDecorator(t *testing.T) {
config["winrm_username"] = "username"
config["winrm_password"] = "password"
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
@ -579,7 +602,8 @@ func TestUserDeviceLoginIsEnabledForLinux(t *testing.T) {
"communicator": "none",
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatalf("failed to use device login for Linux: %s", err)
}
@ -610,7 +634,8 @@ func TestConfigShouldRejectMalformedCaptureNamePrefix(t *testing.T) {
for _, x := range wellFormedCaptureNamePrefix {
config["capture_name_prefix"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Errorf("Expected test to pass, but it failed with the well-formed capture_name_prefix set to %q.", x)
@ -628,7 +653,8 @@ func TestConfigShouldRejectMalformedCaptureNamePrefix(t *testing.T) {
for _, x := range malformedCaptureNamePrefix {
config["capture_name_prefix"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Errorf("Expected test to fail, but it succeeded with the malformed capture_name_prefix set to %q.", x)
@ -660,7 +686,8 @@ func TestConfigShouldRejectMalformedCaptureContainerName(t *testing.T) {
for _, x := range wellFormedCaptureContainerName {
config["capture_container_name"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Errorf("Expected test to pass, but it failed with the well-formed capture_container_name set to %q.", x)
@ -678,7 +705,8 @@ func TestConfigShouldRejectMalformedCaptureContainerName(t *testing.T) {
for _, x := range malformedCaptureContainerName {
config["capture_container_name"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Errorf("Expected test to fail, but it succeeded with the malformed capture_container_name set to %q.", x)
@ -710,7 +738,8 @@ func TestConfigShouldRejectMalformedManagedImageOSDiskSnapshotName(t *testing.T)
for _, x := range wellFormedManagedImageOSDiskSnapshotName {
config["managed_image_os_disk_snapshot_name"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Errorf("Expected test to pass, but it failed with the well-formed managed_image_os_disk_snapshot_name set to %q.", x)
@ -727,7 +756,8 @@ func TestConfigShouldRejectMalformedManagedImageOSDiskSnapshotName(t *testing.T)
for _, x := range malformedManagedImageOSDiskSnapshotName {
config["managed_image_os_disk_snapshot_name"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Errorf("Expected test to fail, but it succeeded with the malformed managed_image_os_disk_snapshot_name set to %q.", x)
@ -760,7 +790,8 @@ func TestConfigShouldRejectMalformedManagedImageDataDiskSnapshotPrefix(t *testin
for _, x := range wellFormedManagedImageDataDiskSnapshotPrefix {
config["managed_image_data_disk_snapshot_prefix"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Errorf("Expected test to pass, but it failed with the well-formed managed_image_data_disk_snapshot_prefix set to %q.", x)
@ -777,7 +808,8 @@ func TestConfigShouldRejectMalformedManagedImageDataDiskSnapshotPrefix(t *testin
for _, x := range malformedManagedImageDataDiskSnapshotPrefix {
config["managed_image_data_disk_snapshot_prefix"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Errorf("Expected test to fail, but it succeeded with the malformed managed_image_data_disk_snapshot_prefix set to %q.", x)
@ -805,7 +837,8 @@ func TestConfigShouldAcceptTags(t *testing.T) {
},
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
@ -855,7 +888,8 @@ func TestConfigShouldRejectTagsInExcessOf15AcceptTags(t *testing.T) {
"azure_tags": tooManyTags,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject based on an excessive amount of tags (> 15)")
@ -887,7 +921,8 @@ func TestConfigShouldRejectExcessiveTagNameLength(t *testing.T) {
"azure_tags": tags,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject tag name based on length (> 512)")
}
@ -918,7 +953,8 @@ func TestConfigShouldRejectExcessiveTagValueLength(t *testing.T) {
"azure_tags": tags,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject tag value based on length (> 256)")
}
@ -935,7 +971,8 @@ func TestConfigZoneResilientShouldDefaultToFalse(t *testing.T) {
"os_type": "linux",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
@ -958,7 +995,8 @@ func TestConfigZoneResilientSetFromConfig(t *testing.T) {
"managed_image_zone_resilient": true,
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
@ -986,7 +1024,8 @@ func TestConfigShouldRejectMissingCustomDataFile(t *testing.T) {
"custom_data_file": "/this/file/does/not/exist",
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject missing custom data file")
}
@ -1006,7 +1045,8 @@ func TestConfigShouldRejectManagedImageOSDiskSnapshotNameWithoutManagedImageName
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject Managed Image build with OS disk snapshot name but without managed image name")
}
@ -1026,7 +1066,8 @@ func TestConfigShouldRejectManagedImageOSDiskSnapshotNameWithoutManagedImageReso
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject Managed Image build with OS disk snapshot name but without managed image resource group name")
}
@ -1046,7 +1087,8 @@ func TestConfigShouldRejectImageDataDiskSnapshotPrefixWithoutManagedImageName(t
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject Managed Image build with data disk snapshot prefix but without managed image name")
}
@ -1066,7 +1108,8 @@ func TestConfigShouldRejectImageDataDiskSnapshotPrefixWithoutManagedImageResourc
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject Managed Image build with data disk snapshot prefix but without managed image resource group name")
}
@ -1088,7 +1131,8 @@ func TestConfigShouldAcceptManagedImageOSDiskSnapshotNameAndManagedImageDataDisk
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal("expected config to accept platform managed image build")
}
@ -1109,7 +1153,8 @@ func TestConfigShouldRejectManagedImageOSDiskSnapshotNameAndManagedImageDataDisk
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject Managed Image build with data disk snapshot prefix and OS disk snapshot name with capture container name")
}
@ -1130,7 +1175,8 @@ func TestConfigShouldRejectManagedImageOSDiskSnapshotNameAndManagedImageDataDisk
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject Managed Image build with data disk snapshot prefix and OS disk snapshot name with capture name prefix")
}
@ -1151,7 +1197,8 @@ func TestConfigShouldAcceptPlatformManagedImageBuild(t *testing.T) {
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal("expected config to accept platform managed image build")
}
@ -1175,7 +1222,8 @@ func TestConfigShouldRejectVhdAndManagedImageOutput(t *testing.T) {
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject VHD and Managed Image build")
}
@ -1195,7 +1243,8 @@ func TestConfigShouldRejectManagedImageSourceAndVhdOutput(t *testing.T) {
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject VHD and Managed Image build")
}
@ -1218,7 +1267,8 @@ func TestConfigShouldRejectCustomAndPlatformManagedImageBuild(t *testing.T) {
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject custom and platform input for a managed image build")
}
@ -1239,7 +1289,8 @@ func TestConfigShouldRejectCustomAndImageUrlForManagedImageBuild(t *testing.T) {
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject custom and platform input for a managed image build")
}
@ -1260,7 +1311,8 @@ func TestConfigShouldRejectMalformedManageImageStorageAccountTypes(t *testing.T)
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject custom and platform input for a managed image build")
}
@ -1281,7 +1333,8 @@ func TestConfigShouldRejectMalformedDiskCachingType(t *testing.T) {
"os_type": constants.Target_Linux,
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject custom and platform input for a managed image build")
}
@ -1305,7 +1358,8 @@ func TestConfigShouldAcceptManagedImageStorageAccountTypes(t *testing.T) {
for _, x := range storage_account_types {
config["managed_image_storage_account_type"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatalf("expected config to accept a managed_image_storage_account_type of %q", x)
}
@ -1330,7 +1384,8 @@ func TestConfigShouldAcceptDiskCachingTypes(t *testing.T) {
for _, x := range storage_account_types {
config["disk_caching_type"] = x
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatalf("expected config to accept a disk_caching_type of %q", x)
}
@ -1355,7 +1410,8 @@ func TestConfigShouldRejectTempAndBuildResourceGroupName(t *testing.T) {
"build_resource_group_name": "rgn00",
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject the use of both temp_resource_group_name and build_resource_group_name")
}
@ -1402,7 +1458,8 @@ func TestConfigShouldRejectInvalidResourceGroupNames(t *testing.T) {
for _, y := range tests {
config[x] = y.name
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if !y.ok && err == nil {
t.Errorf("expected config to reject %q for setting %q", y.name, x)
} else if y.ok && err != nil {
@ -1452,7 +1509,8 @@ func TestConfigShouldRejectManagedDiskNames(t *testing.T) {
for _, y := range testsResourceGroupNames {
config[settingUnderTest] = y.name
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if !y.ok && err == nil {
t.Errorf("expected config to reject %q for setting %q", y.name, settingUnderTest)
} else if y.ok && err != nil {
@ -1486,7 +1544,8 @@ func TestConfigShouldRejectManagedDiskNames(t *testing.T) {
for _, y := range testNames {
config[settingUnderTest] = y.name
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if !y.ok && err == nil {
t.Logf("expected config to reject %q for setting %q", y.name, settingUnderTest)
} else if y.ok && err != nil {
@ -1496,7 +1555,8 @@ func TestConfigShouldRejectManagedDiskNames(t *testing.T) {
}
func TestConfigAdditionalDiskDefaultIsNil(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
if c.AdditionalDiskSize != nil {
t.Errorf("Expected Config to not have a set of additional disks, but got a non nil value")
}
@ -1519,7 +1579,8 @@ func TestConfigAdditionalDiskOverrideDefault(t *testing.T) {
"disk_additional_size": {32, 64},
}
c, _, _ := newConfig(config, diskconfig, getPackerConfiguration())
var c Config
c.Prepare(config, diskconfig, getPackerConfiguration())
if c.AdditionalDiskSize == nil {
t.Errorf("Expected Config to have a set of additional disks, but got nil")
}
@ -1561,19 +1622,20 @@ func TestPlanInfoConfiguration(t *testing.T) {
}
config["plan_info"] = planInfo
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject the use of plan_name without plan_product and plan_publisher")
}
planInfo["plan_product"] = "--plan-product--"
_, _, err = newConfig(config, getPackerConfiguration())
_, err = c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject the use of plan_name and plan_product without plan_publisher")
}
planInfo["plan_publisher"] = "--plan-publisher--"
c, _, err := newConfig(config, getPackerConfiguration())
_, err = c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatalf("expected config to accept a complete plan configuration: %s", err)
}
@ -1610,7 +1672,8 @@ func TestPlanInfoPromotionCode(t *testing.T) {
},
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatalf("expected config to accept plan_info configuration, but got %s", err)
}
@ -1659,7 +1722,8 @@ func TestPlanInfoTooManyTagsErrors(t *testing.T) {
},
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Fatal("expected config to reject configuration due to excess tags")
}
@ -1682,7 +1746,8 @@ func TestConfigShouldAllowTempNameOverrides(t *testing.T) {
"temp_compute_name": "myTempComputeName",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Errorf("newConfig failed with %q", err)
}
@ -1716,7 +1781,8 @@ func TestConfigShouldAllowAsyncResourceGroupOverride(t *testing.T) {
"async_resourcegroup_delete": "true",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Errorf("newConfig failed with %q", err)
}
@ -1738,7 +1804,8 @@ func TestConfigShouldAllowAsyncResourceGroupOverrideNoValue(t *testing.T) {
"managed_image_resource_group_name": "ignore",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Errorf("newConfig failed with %q", err)
}
@ -1761,10 +1828,10 @@ func TestConfigShouldAllowAsyncResourceGroupOverrideBadValue(t *testing.T) {
"async_resourcegroup_delete": "asdasda",
}
c, _, err := newConfig(config, getPackerConfiguration())
if err != nil && c == nil {
t.Log("newConfig failed which is expected ", err)
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Log("newConfig failed which is expected ", err)
}
}
@ -1782,7 +1849,8 @@ func TestConfigShouldAllowSharedImageGalleryOptions(t *testing.T) {
},
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err == nil {
t.Log("expected config to accept Shared Image Gallery options", err)
}
@ -1807,7 +1875,8 @@ func TestConfigShouldRejectSharedImageGalleryWithVhdTarget(t *testing.T) {
"capture_name_prefix": "ignore",
}
_, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Log("expected an error if Shared Image Gallery source is used with VHD target", err)
}
@ -1818,7 +1887,8 @@ func Test_GivenZoneNotSupportingResiliency_ConfigValidate_ShouldWarn(t *testing.
builderValues["managed_image_zone_resilient"] = "true"
builderValues["location"] = "ukwest"
c, _, err := newConfig(builderValues, getPackerConfiguration())
var c Config
_, err := c.Prepare(builderValues, getPackerConfiguration())
if err != nil {
t.Errorf("newConfig failed with %q", err)
}
@ -1836,7 +1906,8 @@ func Test_GivenZoneSupportingResiliency_ConfigValidate_ShouldNotWarn(t *testing.
builderValues["managed_image_zone_resilient"] = "true"
builderValues["location"] = "westeurope"
c, _, err := newConfig(builderValues, getPackerConfiguration())
var c Config
_, err := c.Prepare(builderValues, getPackerConfiguration())
if err != nil {
t.Errorf("newConfig failed with %q", err)
}

View File

@ -5,14 +5,15 @@ import (
)
func TestResourceResolverIgnoresEmptyVirtualNetworkName(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
if c.VirtualNetworkName != "" {
t.Fatalf("Expected VirtualNetworkName to be empty by default")
}
sut := newTestResourceResolver()
sut.findVirtualNetworkResourceGroup = nil // assert that this is not even called
sut.Resolve(c)
sut.Resolve(&c)
if c.VirtualNetworkName != "" {
t.Fatalf("Expected VirtualNetworkName to be empty")
@ -25,7 +26,8 @@ func TestResourceResolverIgnoresEmptyVirtualNetworkName(t *testing.T) {
// If the user fully specified the virtual network name and resource group then
// there is no need to do a lookup.
func TestResourceResolverIgnoresSetVirtualNetwork(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
c.VirtualNetworkName = "--virtual-network-name--"
c.VirtualNetworkResourceGroupName = "--virtual-network-resource-group-name--"
c.VirtualNetworkSubnetName = "--virtual-network-subnet-name--"
@ -33,7 +35,7 @@ func TestResourceResolverIgnoresSetVirtualNetwork(t *testing.T) {
sut := newTestResourceResolver()
sut.findVirtualNetworkResourceGroup = nil // assert that this is not even called
sut.findVirtualNetworkSubnet = nil // assert that this is not even called
sut.Resolve(c)
sut.Resolve(&c)
if c.VirtualNetworkName != "--virtual-network-name--" {
t.Fatalf("Expected VirtualNetworkName to be --virtual-network-name--")
@ -49,11 +51,12 @@ func TestResourceResolverIgnoresSetVirtualNetwork(t *testing.T) {
// If the user set virtual network name then the code should resolve virtual network
// resource group name.
func TestResourceResolverSetVirtualNetworkResourceGroupName(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
c.VirtualNetworkName = "--virtual-network-name--"
sut := newTestResourceResolver()
sut.Resolve(c)
sut.Resolve(&c)
if c.VirtualNetworkResourceGroupName != "findVirtualNetworkResourceGroup is mocked" {
t.Fatalf("Expected VirtualNetworkResourceGroupName to be 'findVirtualNetworkResourceGroup is mocked'")

View File

@ -3,7 +3,9 @@ package arm
import (
"context"
"fmt"
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-03-01/compute"
"github.com/Azure/go-autorest/autorest/date"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
@ -11,7 +13,7 @@ import (
type StepPublishToSharedImageGallery struct {
client *AzureClient
publish func(ctx context.Context, mdiID, miSigPubRg, miSIGalleryName, miSGImageName, miSGImageVersion string, miSigReplicationRegions []string, location string, tags map[string]*string) (string, error)
publish func(ctx context.Context, mdiID, miSigPubRg, miSIGalleryName, miSGImageName, miSGImageVersion string, miSigReplicationRegions []string, miSGImageVersionEndOfLifeDate string, miSGImageVersionExcludeFromLatest bool, miSigReplicaCount int32, location string, tags map[string]*string) (string, error)
say func(message string)
error func(e error)
toSIG func() bool
@ -35,7 +37,7 @@ func NewStepPublishToSharedImageGallery(client *AzureClient, ui packer.Ui, confi
return step
}
func (s *StepPublishToSharedImageGallery) publishToSig(ctx context.Context, mdiID string, miSigPubRg string, miSIGalleryName string, miSGImageName string, miSGImageVersion string, miSigReplicationRegions []string, location string, tags map[string]*string) (string, error) {
func (s *StepPublishToSharedImageGallery) publishToSig(ctx context.Context, mdiID string, miSigPubRg string, miSIGalleryName string, miSGImageName string, miSGImageVersion string, miSigReplicationRegions []string, miSGImageVersionEndOfLifeDate string, miSGImageVersionExcludeFromLatest bool, miSigReplicaCount int32, location string, tags map[string]*string) (string, error) {
replicationRegions := make([]compute.TargetRegion, len(miSigReplicationRegions))
for i, v := range miSigReplicationRegions {
@ -43,6 +45,17 @@ func (s *StepPublishToSharedImageGallery) publishToSig(ctx context.Context, mdiI
replicationRegions[i] = compute.TargetRegion{Name: &regionName}
}
var endOfLifeDate *date.Time
if miSGImageVersionEndOfLifeDate != "" {
parseDate, err := date.ParseTime("2006-01-02T15:04:05.99Z", miSGImageVersionEndOfLifeDate)
if err != nil {
s.say(fmt.Sprintf("Error parsing date from shared_gallery_image_version_end_of_life_date: %s", err))
return "", err
}
endOfLifeDate = &date.Time{Time: parseDate}
} else {
endOfLifeDate = (*date.Time)(nil)
}
galleryImageVersion := compute.GalleryImageVersion{
Location: &location,
Tags: tags,
@ -53,7 +66,10 @@ func (s *StepPublishToSharedImageGallery) publishToSig(ctx context.Context, mdiI
ID: &mdiID,
},
},
TargetRegions: &replicationRegions,
TargetRegions: &replicationRegions,
EndOfLifeDate: endOfLifeDate,
ExcludeFromLatest: &miSGImageVersionExcludeFromLatest,
ReplicaCount: &miSigReplicaCount,
},
},
}
@ -101,14 +117,27 @@ func (s *StepPublishToSharedImageGallery) Run(ctx context.Context, stateBag mult
var targetManagedImageName = stateBag.Get(constants.ArmManagedImageName).(string)
var managedImageSubscription = stateBag.Get(constants.ArmManagedImageSubscription).(string)
var mdiID = fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/images/%s", managedImageSubscription, targetManagedImageResourceGroupName, targetManagedImageName)
miSGImageVersionEndOfLifeDate, _ := stateBag.Get(constants.ArmManagedImageSharedGalleryImageVersionEndOfLifeDate).(string)
miSGImageVersionExcludeFromLatest, _ := stateBag.Get(constants.ArmManagedImageSharedGalleryImageVersionExcludeFromLatest).(bool)
miSigReplicaCount, _ := stateBag.Get(constants.ArmManagedImageSharedGalleryImageVersionReplicaCount).(int32)
// Replica count must be between 1 and 10 inclusive.
if miSigReplicaCount <= 0 {
miSigReplicaCount = constants.SharedImageGalleryImageVersionDefaultMinReplicaCount
} else if miSigReplicaCount > 10 {
miSigReplicaCount = constants.SharedImageGalleryImageVersionDefaultMaxReplicaCount
}
s.say(fmt.Sprintf(" -> MDI ID used for SIG publish : '%s'", mdiID))
s.say(fmt.Sprintf(" -> SIG publish resource group : '%s'", miSigPubRg))
s.say(fmt.Sprintf(" -> SIG gallery name : '%s'", miSIGalleryName))
s.say(fmt.Sprintf(" -> SIG image name : '%s'", miSGImageName))
s.say(fmt.Sprintf(" -> SIG image version : '%s'", miSGImageVersion))
s.say(fmt.Sprintf(" -> SIG replication regions : '%v'", miSigReplicationRegions))
createdGalleryImageVersionID, err := s.publish(ctx, mdiID, miSigPubRg, miSIGalleryName, miSGImageName, miSGImageVersion, miSigReplicationRegions, location, tags)
s.say(fmt.Sprintf(" -> MDI ID used for SIG publish : '%s'", mdiID))
s.say(fmt.Sprintf(" -> SIG publish resource group : '%s'", miSigPubRg))
s.say(fmt.Sprintf(" -> SIG gallery name : '%s'", miSIGalleryName))
s.say(fmt.Sprintf(" -> SIG image name : '%s'", miSGImageName))
s.say(fmt.Sprintf(" -> SIG image version : '%s'", miSGImageVersion))
s.say(fmt.Sprintf(" -> SIG replication regions : '%v'", miSigReplicationRegions))
s.say(fmt.Sprintf(" -> SIG image version endoflife date : '%s'", miSGImageVersionEndOfLifeDate))
s.say(fmt.Sprintf(" -> SIG image version exclude from latest : '%t'", miSGImageVersionExcludeFromLatest))
s.say(fmt.Sprintf(" -> SIG replica count [1, 10] : '%d'", miSigReplicaCount))
createdGalleryImageVersionID, err := s.publish(ctx, mdiID, miSigPubRg, miSIGalleryName, miSGImageName, miSGImageVersion, miSigReplicationRegions, miSGImageVersionEndOfLifeDate, miSGImageVersionExcludeFromLatest, miSigReplicaCount, location, tags)
if err != nil {
stateBag.Put(constants.Error, err)

View File

@ -2,14 +2,15 @@ package arm
import (
"context"
"testing"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/helper/multistep"
"testing"
)
func TestStepPublishToSharedImageGalleryShouldNotPublishForVhd(t *testing.T) {
var testSubject = &StepPublishToSharedImageGallery{
publish: func(context.Context, string, string, string, string, string, []string, string, map[string]*string) (string, error) {
publish: func(context.Context, string, string, string, string, string, []string, string, bool, int32, string, map[string]*string) (string, error) {
return "test", nil
},
say: func(message string) {},
@ -30,7 +31,7 @@ func TestStepPublishToSharedImageGalleryShouldNotPublishForVhd(t *testing.T) {
func TestStepPublishToSharedImageGalleryShouldPublishForManagedImageWithSig(t *testing.T) {
var testSubject = &StepPublishToSharedImageGallery{
publish: func(context.Context, string, string, string, string, string, []string, string, map[string]*string) (string, error) {
publish: func(context.Context, string, string, string, string, string, []string, string, bool, int32, string, map[string]*string) (string, error) {
return "", nil
},
say: func(message string) {},

View File

@ -1,25 +0,0 @@
package arm
import (
"context"
commonhelper "github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
type StepSaveWinRMPassword struct {
Password string
BuildName string
}
func (s *StepSaveWinRMPassword) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
// store so that we can access this later during provisioning
commonhelper.SetSharedState("winrm_password", s.Password, s.BuildName)
packer.LogSecretFilter.Set(s.Password)
return multistep.ActionContinue
}
func (s *StepSaveWinRMPassword) Cleanup(multistep.StateBag) {
commonhelper.RemoveSharedStateFile("winrm_password", s.BuildName)
}

View File

@ -13,8 +13,9 @@ import (
// Ensure the link values are not set, and the concrete values are set.
func TestVirtualMachineDeployment00(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(c)
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -42,8 +43,9 @@ func TestVirtualMachineDeployment00(t *testing.T) {
// Ensure the Virtual Machine template is a valid JSON document.
func TestVirtualMachineDeployment01(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(c)
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -56,8 +58,9 @@ func TestVirtualMachineDeployment01(t *testing.T) {
// Ensure the Virtual Machine template parameters are correct.
func TestVirtualMachineDeployment02(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(c)
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -104,8 +107,9 @@ func TestVirtualMachineDeployment03(t *testing.T) {
m["image_sku"] = "ImageSku"
m["image_version"] = "ImageVersion"
c, _, _ := newConfig(m, getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(c)
var c Config
c.Prepare(m, getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -130,12 +134,13 @@ func TestVirtualMachineDeployment04(t *testing.T) {
"communicator": "none",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -162,12 +167,13 @@ func TestVirtualMachineDeployment05(t *testing.T) {
"virtual_network_subnet_name": "virtualNetworkSubnetName",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -197,12 +203,13 @@ func TestVirtualMachineDeployment06(t *testing.T) {
},
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -227,7 +234,8 @@ func TestVirtualMachineDeployment07(t *testing.T) {
"communicator": "none",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
@ -247,7 +255,7 @@ growpart:
base64CustomData := base64.StdEncoding.EncodeToString([]byte(customData))
c.customData = base64CustomData
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -271,12 +279,13 @@ func TestVirtualMachineDeployment08(t *testing.T) {
"managed_image_resource_group_name": "ManagedImageResourceGroupName",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -302,12 +311,13 @@ func TestVirtualMachineDeployment09(t *testing.T) {
"managed_image_resource_group_name": "ManagedImageResourceGroupName",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -339,12 +349,13 @@ func TestVirtualMachineDeployment10(t *testing.T) {
"managed_image_resource_group_name": "ManagedImageResourceGroupName",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -375,12 +386,13 @@ func TestVirtualMachineDeployment11(t *testing.T) {
"capture_container_name": "packerimages",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -409,12 +421,13 @@ func TestVirtualMachineDeployment12(t *testing.T) {
"managed_image_resource_group_name": "ManagedImageResourceGroupName",
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -442,13 +455,14 @@ func TestVirtualMachineDeployment13(t *testing.T) {
"allowed_inbound_ip_addresses": []string{"127.0.0.1", "192.168.100.0/24"},
}
c, _, err := newConfig(config, getPackerConfiguration())
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
c.tmpKeyVaultName = "--keyvault-name--"
deployment, err := GetVirtualMachineDeployment(c)
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -461,8 +475,9 @@ func TestVirtualMachineDeployment13(t *testing.T) {
// Ensure the link values are not set, and the concrete values are set.
func TestKeyVaultDeployment00(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetKeyVaultDeployment(c)
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetKeyVaultDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -490,8 +505,9 @@ func TestKeyVaultDeployment00(t *testing.T) {
// Ensure the KeyVault template is a valid JSON document.
func TestKeyVaultDeployment01(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetKeyVaultDeployment(c)
var c Config
c.Prepare(getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetKeyVaultDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -504,9 +520,10 @@ func TestKeyVaultDeployment01(t *testing.T) {
// Ensure the KeyVault template parameters are correct.
func TestKeyVaultDeployment02(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfigurationWithWindows(), getPackerConfiguration())
var c Config
c.Prepare(getArmBuilderConfigurationWithWindows(), getPackerConfiguration())
deployment, err := GetKeyVaultDeployment(c)
deployment, err := GetKeyVaultDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -546,8 +563,9 @@ func TestKeyVaultDeployment03(t *testing.T) {
},
}
c, _, _ := newConfig(tags, getArmBuilderConfigurationWithWindows(), getPackerConfiguration())
deployment, err := GetKeyVaultDeployment(c)
var c Config
c.Prepare(tags, getArmBuilderConfigurationWithWindows(), getPackerConfiguration())
deployment, err := GetKeyVaultDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -567,8 +585,9 @@ func TestPlanInfo01(t *testing.T) {
},
}
c, _, _ := newConfig(planInfo, getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(c)
var c Config
c.Prepare(planInfo, getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}
@ -592,8 +611,9 @@ func TestPlanInfo02(t *testing.T) {
},
}
c, _, _ := newConfig(planInfo, getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(c)
var c Config
c.Prepare(planInfo, getArmBuilderConfiguration(), getPackerConfiguration())
deployment, err := GetVirtualMachineDeployment(&c)
if err != nil {
t.Fatal(err)
}

View File

@ -1,4 +1,5 @@
//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config
// Package chroot is able to create an Azure managed image without requiring the
// launch of a new virtual machine for every build. It does this by attaching and
@ -14,6 +15,7 @@ import (
"runtime"
"strings"
"github.com/hashicorp/hcl/v2/hcldec"
azcommon "github.com/hashicorp/packer/builder/azure/common"
"github.com/hashicorp/packer/builder/azure/common/client"
"github.com/hashicorp/packer/common"
@ -116,7 +118,9 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs = azcommon.TemplateFuncs
b.config.ctx.Funcs["vm"] = CreateVMMetadataTemplateFunc()
err := config.Decode(&b.config, &config.DecodeOpts{
@ -134,7 +138,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
},
}, raws...)
if err != nil {
return nil, err
return nil, nil, err
}
var errs *packer.MultiError
@ -143,7 +147,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
// Defaults
err = b.config.ClientConfig.SetDefaultValues()
if err != nil {
return nil, err
return nil, nil, err
}
if b.config.ChrootMounts == nil {
@ -254,11 +258,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
if errs != nil {
return warns, errs
return nil, warns, errs
}
packer.LogSecretFilter.Set(b.config.ClientConfig.ClientSecret, b.config.ClientConfig.ClientJWT)
return warns, nil
return nil, warns, nil
}
func checkDiskCacheType(s string) interface{} {

View File

@ -0,0 +1,92 @@
// Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT.
package chroot
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
CloudEnvironmentName *string `mapstructure:"cloud_environment_name" required:"false" cty:"cloud_environment_name"`
ClientID *string `mapstructure:"client_id" cty:"client_id"`
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret"`
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path"`
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt"`
ObjectID *string `mapstructure:"object_id" cty:"object_id"`
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id"`
SubscriptionID *string `mapstructure:"subscription_id" cty:"subscription_id"`
FromScratch *bool `mapstructure:"from_scratch" cty:"from_scratch"`
Source *string `mapstructure:"source" required:"true" cty:"source"`
CommandWrapper *string `mapstructure:"command_wrapper" cty:"command_wrapper"`
PreMountCommands []string `mapstructure:"pre_mount_commands" cty:"pre_mount_commands"`
MountOptions []string `mapstructure:"mount_options" cty:"mount_options"`
MountPartition *string `mapstructure:"mount_partition" cty:"mount_partition"`
MountPath *string `mapstructure:"mount_path" cty:"mount_path"`
PostMountCommands []string `mapstructure:"post_mount_commands" cty:"post_mount_commands"`
ChrootMounts [][]string `mapstructure:"chroot_mounts" cty:"chroot_mounts"`
CopyFiles []string `mapstructure:"copy_files" cty:"copy_files"`
TemporaryOSDiskName *string `mapstructure:"temporary_os_disk_name" cty:"temporary_os_disk_name"`
OSDiskSizeGB *int32 `mapstructure:"os_disk_size_gb" cty:"os_disk_size_gb"`
OSDiskStorageAccountType *string `mapstructure:"os_disk_storage_account_type" cty:"os_disk_storage_account_type"`
OSDiskCacheType *string `mapstructure:"os_disk_cache_type" cty:"os_disk_cache_type"`
OSDiskSkipCleanup *bool `mapstructure:"os_disk_skip_cleanup" cty:"os_disk_skip_cleanup"`
ImageResourceID *string `mapstructure:"image_resource_id" required:"true" cty:"image_resource_id"`
ImageHyperVGeneration *string `mapstructure:"image_hyperv_generation" cty:"image_hyperv_generation"`
}
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"cloud_environment_name": &hcldec.AttrSpec{Name: "cloud_environment_name", Type: cty.String, Required: false},
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
"subscription_id": &hcldec.AttrSpec{Name: "subscription_id", Type: cty.String, Required: false},
"from_scratch": &hcldec.AttrSpec{Name: "from_scratch", Type: cty.Bool, Required: false},
"source": &hcldec.AttrSpec{Name: "source", Type: cty.String, Required: false},
"command_wrapper": &hcldec.AttrSpec{Name: "command_wrapper", Type: cty.String, Required: false},
"pre_mount_commands": &hcldec.AttrSpec{Name: "pre_mount_commands", Type: cty.List(cty.String), Required: false},
"mount_options": &hcldec.AttrSpec{Name: "mount_options", Type: cty.List(cty.String), Required: false},
"mount_partition": &hcldec.AttrSpec{Name: "mount_partition", Type: cty.String, Required: false},
"mount_path": &hcldec.AttrSpec{Name: "mount_path", Type: cty.String, Required: false},
"post_mount_commands": &hcldec.AttrSpec{Name: "post_mount_commands", Type: cty.List(cty.String), Required: false},
"chroot_mounts": &hcldec.BlockListSpec{TypeName: "chroot_mounts", Nested: &hcldec.AttrSpec{Name: "chroot_mounts", Type: cty.List(cty.String), Required: false}},
"copy_files": &hcldec.AttrSpec{Name: "copy_files", Type: cty.List(cty.String), Required: false},
"temporary_os_disk_name": &hcldec.AttrSpec{Name: "temporary_os_disk_name", Type: cty.String, Required: false},
"os_disk_size_gb": &hcldec.AttrSpec{Name: "os_disk_size_gb", Type: cty.Number, Required: false},
"os_disk_storage_account_type": &hcldec.AttrSpec{Name: "os_disk_storage_account_type", Type: cty.String, Required: false},
"os_disk_cache_type": &hcldec.AttrSpec{Name: "os_disk_cache_type", Type: cty.String, Required: false},
"os_disk_skip_cleanup": &hcldec.AttrSpec{Name: "os_disk_skip_cleanup", Type: cty.Bool, Required: false},
"image_resource_id": &hcldec.AttrSpec{Name: "image_resource_id", Type: cty.String, Required: false},
"image_hyperv_generation": &hcldec.AttrSpec{Name: "image_hyperv_generation", Type: cty.String, Required: false},
}
return s
}

View File

@ -55,7 +55,7 @@ func TestBuilder_Prepare(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
b := &Builder{}
_, err := b.Prepare(tt.config)
_, _, err := b.Prepare(tt.config)
if (err != nil) != tt.wantErr {
t.Errorf("Builder.Prepare() error = %v, wantErr %v", err, tt.wantErr)

View File

@ -2,9 +2,10 @@ package chroot
import (
"context"
"github.com/Azure/go-autorest/autorest/to"
"testing"
"github.com/Azure/go-autorest/autorest/to"
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-03-01/compute"
"github.com/hashicorp/packer/builder/azure/common/client"
"github.com/stretchr/testify/assert"

View File

@ -3,13 +3,14 @@ package chroot
import (
"context"
"fmt"
"log"
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-03-01/compute"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/to"
"github.com/hashicorp/packer/builder/azure/common/client"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"log"
)
var _ multistep.Step = &StepCreateImage{}

View File

@ -3,11 +3,12 @@ package client
import (
"context"
"fmt"
"regexp"
"strings"
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute/computeapi"
"github.com/Azure/go-autorest/autorest/to"
"regexp"
"strings"
)
var platformImageRegex = regexp.MustCompile(`^[-_.a-zA-Z0-9]+:[-_.a-zA-Z0-9]+:[-_.a-zA-Z0-9]+:[-_.a-zA-Z0-9]+$`)

View File

@ -9,6 +9,13 @@ const (
Thumbprint string = "thumbprint"
Ui string = "ui"
)
// Default replica count for image versions in shared image gallery
const (
SharedImageGalleryImageVersionDefaultMinReplicaCount int32 = 1
SharedImageGalleryImageVersionDefaultMaxReplicaCount int32 = 10
)
const (
ArmCaptureTemplate string = "arm.CaptureTemplate"
ArmComputeName string = "arm.ComputeName"
@ -30,18 +37,21 @@ const (
ArmVirtualMachineCaptureParameters string = "arm.VirtualMachineCaptureParameters"
ArmIsExistingResourceGroup string = "arm.IsExistingResourceGroup"
ArmIsManagedImage string = "arm.IsManagedImage"
ArmManagedImageResourceGroupName string = "arm.ManagedImageResourceGroupName"
ArmManagedImageLocation string = "arm.ManagedImageLocation"
ArmManagedImageName string = "arm.ManagedImageName"
ArmManagedImageSigPublishResourceGroup string = "arm.ManagedImageSigPublishResourceGroup"
ArmManagedImageSharedGalleryName string = "arm.ManagedImageSharedGalleryName"
ArmManagedImageSharedGalleryImageName string = "arm.ManagedImageSharedGalleryImageName"
ArmManagedImageSharedGalleryImageVersion string = "arm.ManagedImageSharedGalleryImageVersion"
ArmManagedImageSharedGalleryReplicationRegions string = "arm.ManagedImageSharedGalleryReplicationRegions"
ArmManagedImageSharedGalleryId string = "arm.ArmManagedImageSharedGalleryId"
ArmManagedImageSubscription string = "arm.ArmManagedImageSubscription"
ArmAsyncResourceGroupDelete string = "arm.AsyncResourceGroupDelete"
ArmManagedImageOSDiskSnapshotName string = "arm.ManagedImageOSDiskSnapshotName"
ArmManagedImageDataDiskSnapshotPrefix string = "arm.ManagedImageDataDiskSnapshotPrefix"
ArmIsManagedImage string = "arm.IsManagedImage"
ArmManagedImageResourceGroupName string = "arm.ManagedImageResourceGroupName"
ArmManagedImageLocation string = "arm.ManagedImageLocation"
ArmManagedImageName string = "arm.ManagedImageName"
ArmManagedImageSigPublishResourceGroup string = "arm.ManagedImageSigPublishResourceGroup"
ArmManagedImageSharedGalleryName string = "arm.ManagedImageSharedGalleryName"
ArmManagedImageSharedGalleryImageName string = "arm.ManagedImageSharedGalleryImageName"
ArmManagedImageSharedGalleryImageVersion string = "arm.ManagedImageSharedGalleryImageVersion"
ArmManagedImageSharedGalleryReplicationRegions string = "arm.ManagedImageSharedGalleryReplicationRegions"
ArmManagedImageSharedGalleryId string = "arm.ArmManagedImageSharedGalleryId"
ArmManagedImageSharedGalleryImageVersionEndOfLifeDate string = "arm.ArmManagedImageSharedGalleryImageVersionEndOfLifeDate"
ArmManagedImageSharedGalleryImageVersionReplicaCount string = "arm.ArmManagedImageSharedGalleryImageVersionReplicaCount"
ArmManagedImageSharedGalleryImageVersionExcludeFromLatest string = "arm.ArmManagedImageSharedGalleryImageVersionExcludeFromLatest"
ArmManagedImageSubscription string = "arm.ArmManagedImageSubscription"
ArmAsyncResourceGroupDelete string = "arm.AsyncResourceGroupDelete"
ArmManagedImageOSDiskSnapshotName string = "arm.ManagedImageOSDiskSnapshotName"
ArmManagedImageDataDiskSnapshotPrefix string = "arm.ManagedImageDataDiskSnapshotPrefix"
)

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
@ -15,20 +16,20 @@ const BuilderId = "packer.cloudstack"
// Builder represents the CloudStack builder.
type Builder struct {
config *Config
config Config
runner multistep.Runner
ui packer.Ui
}
// Prepare implements the packer.Builder interface.
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
config, errs := NewConfig(raws...)
if errs != nil {
return nil, errs
}
b.config = config
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
return nil, nil
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
errs := b.config.Prepare(raws...)
if errs != nil {
return nil, nil, errs
}
return nil, nil, nil
}
// Run implements the packer.Builder interface.
@ -52,7 +53,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
// Set up the state.
state := new(multistep.BasicStateBag)
state.Put("client", client)
state.Put("config", b.config)
state.Put("config", &b.config)
state.Put("hook", hook)
state.Put("ui", ui)
@ -109,7 +110,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
// Build the artifact and return it
artifact := &Artifact{
client: client,
config: b.config,
config: &b.config,
template: state.Get("template").(*cloudstack.CreateTemplateResponse),
}

View File

@ -40,10 +40,8 @@ func TestBuilder_Prepare(t *testing.T) {
},
}
b := &Builder{}
for desc, tc := range cases {
_, errs := b.Prepare(tc.Config)
_, _, errs := (&Builder{}).Prepare(tc.Config)
if tc.Err {
if errs == nil {

View File

@ -167,8 +167,7 @@ type Config struct {
}
// NewConfig parses and validates the given config.
func NewConfig(raws ...interface{}) (*Config, error) {
c := new(Config)
func (c *Config) Prepare(raws ...interface{}) error {
err := config.Decode(c, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &c.ctx,
@ -179,7 +178,7 @@ func NewConfig(raws ...interface{}) (*Config, error) {
},
}, raws...)
if err != nil {
return nil, err
return err
}
var errs *packer.MultiError
@ -309,8 +308,8 @@ func NewConfig(raws ...interface{}) (*Config, error) {
// Check for errors and return if we have any.
if errs != nil && len(errs.Errors) > 0 {
return nil, errs
return errs
}
return c, nil
return nil
}

View File

@ -49,8 +49,8 @@ type FlatConfig struct {
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
@ -104,10 +104,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},

View File

@ -132,7 +132,8 @@ func TestNewConfig(t *testing.T) {
raw[tc.Nullify] = nil
}
_, errs := NewConfig(raw)
var c Config
errs := c.Prepare(raw)
if tc.Err {
if errs == nil {

View File

@ -10,6 +10,7 @@ import (
"net/url"
"github.com/digitalocean/godo"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
@ -25,14 +26,15 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
c, warnings, errs := NewConfig(raws...)
if errs != nil {
return warnings, errs
}
b.config = *c
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
return nil, nil
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
warnings, errs := b.config.Prepare(raws...)
if errs != nil {
return nil, warnings, errs
}
return nil, nil, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {

View File

@ -32,7 +32,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) {
"api_key": []string{},
}
warnings, err := b.Prepare(c)
_, warnings, err := b.Prepare(c)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -47,7 +47,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -62,7 +62,7 @@ func TestBuilderPrepare_Region(t *testing.T) {
// Test default
delete(config, "region")
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -75,7 +75,7 @@ func TestBuilderPrepare_Region(t *testing.T) {
// Test set
config["region"] = expected
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -94,7 +94,7 @@ func TestBuilderPrepare_Size(t *testing.T) {
// Test default
delete(config, "size")
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -107,7 +107,7 @@ func TestBuilderPrepare_Size(t *testing.T) {
// Test set
config["size"] = expected
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -126,7 +126,7 @@ func TestBuilderPrepare_Image(t *testing.T) {
// Test default
delete(config, "image")
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -139,7 +139,7 @@ func TestBuilderPrepare_Image(t *testing.T) {
// Test set
config["image"] = expected
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -157,7 +157,7 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) {
config := testConfig()
// Test default
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -172,7 +172,7 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) {
// Test set
config["state_timeout"] = "5m"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -183,7 +183,7 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) {
// Test bad
config["state_timeout"] = "tubes"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -197,7 +197,7 @@ func TestBuilderPrepare_SnapshotTimeout(t *testing.T) {
config := testConfig()
// Test default
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -212,7 +212,7 @@ func TestBuilderPrepare_SnapshotTimeout(t *testing.T) {
// Test set
config["snapshot_timeout"] = "15m"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -223,7 +223,7 @@ func TestBuilderPrepare_SnapshotTimeout(t *testing.T) {
// Test bad
config["snapshot_timeout"] = "badstring"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -237,7 +237,7 @@ func TestBuilderPrepare_PrivateNetworking(t *testing.T) {
config := testConfig()
// Test default
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -252,7 +252,7 @@ func TestBuilderPrepare_PrivateNetworking(t *testing.T) {
// Test set
config["private_networking"] = true
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -270,7 +270,7 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) {
config := testConfig()
// Test default
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -285,7 +285,7 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) {
// Test set
config["snapshot_name"] = "foobarbaz"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -296,7 +296,7 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) {
// Test set with template
config["snapshot_name"] = "{{timestamp}}"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -316,7 +316,7 @@ func TestBuilderPrepare_DropletName(t *testing.T) {
config := testConfig()
// Test default
warnings, err := b.Prepare(config)
_, warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -331,7 +331,7 @@ func TestBuilderPrepare_DropletName(t *testing.T) {
// Test normal set
config["droplet_name"] = "foobar"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -342,7 +342,7 @@ func TestBuilderPrepare_DropletName(t *testing.T) {
// Test with template
config["droplet_name"] = "foobar-{{timestamp}}"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
@ -353,7 +353,7 @@ func TestBuilderPrepare_DropletName(t *testing.T) {
// Test with bad template
config["droplet_name"] = "foobar-{{"
b = Builder{}
warnings, err = b.Prepare(config)
_, warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}

View File

@ -89,8 +89,7 @@ type Config struct {
ctx interpolate.Context
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
c := new(Config)
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
var md mapstructure.Metadata
err := config.Decode(c, &config.DecodeOpts{
@ -104,7 +103,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
},
}, raws...)
if err != nil {
return nil, nil, err
return nil, err
}
// Defaults
@ -189,9 +188,9 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
return nil, errs
}
packer.LogSecretFilter.Set(c.APIToken)
return c, nil, nil
return nil, nil
}

View File

@ -46,8 +46,8 @@ type FlatConfig struct {
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
@ -77,10 +77,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},

View File

@ -63,6 +63,9 @@ func (s *stepCreateDroplet) Run(ctx context.Context, state multistep.StateBag) m
// Store the droplet id for later
state.Put("droplet_id", droplet.ID)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", droplet.ID)
return multistep.ActionContinue
}

View File

@ -4,6 +4,7 @@ import (
"context"
"log"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
@ -16,18 +17,19 @@ const (
)
type Builder struct {
config *Config
config Config
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
c, warnings, errs := NewConfig(raws...)
if errs != nil {
return warnings, errs
}
b.config = c
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
return warnings, nil
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
warnings, errs := b.config.Prepare(raws...)
if errs != nil {
return nil, warnings, errs
}
return nil, warnings, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
@ -75,7 +77,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)
state.Put("config", b.config)
state.Put("config", &b.config)
state.Put("hook", hook)
state.Put("ui", ui)

View File

@ -35,7 +35,7 @@ func TestUploadDownload(t *testing.T) {
// Setup the builder
builder := &Builder{}
warnings, err := builder.Prepare(tpl.Builders["docker"].Config)
_, warnings, err := builder.Prepare(tpl.Builders["docker"].Config)
if err != nil {
t.Fatalf("Error preparing configuration %s", err)
}
@ -118,7 +118,7 @@ func TestLargeDownload(t *testing.T) {
// Setup the builder
builder := &Builder{}
warnings, err := builder.Prepare(tpl.Builders["docker"].Config)
_, warnings, err := builder.Prepare(tpl.Builders["docker"].Config)
if err != nil {
t.Fatalf("Error preparing configuration %s", err)
}
@ -222,7 +222,7 @@ func TestFixUploadOwner(t *testing.T) {
// Setup the builder
builder := &Builder{}
warnings, err := builder.Prepare(tpl.Builders["docker"].Config)
_, warnings, err := builder.Prepare(tpl.Builders["docker"].Config)
if err != nil {
t.Fatalf("Error preparing configuration %s", err)
}

View File

@ -107,8 +107,7 @@ type Config struct {
ctx interpolate.Context
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
c := new(Config)
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
c.FixUploadOwner = true
@ -124,7 +123,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
},
}, raws...)
if err != nil {
return nil, nil, err
return nil, err
}
// Defaults
@ -191,8 +190,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
return nil, errs
}
return c, nil, nil
return nil, nil
}

View File

@ -46,8 +46,8 @@ type FlatConfig struct {
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
@ -86,10 +86,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},

View File

@ -14,7 +14,8 @@ func testConfig() map[string]interface{} {
}
func testConfigStruct(t *testing.T) *Config {
c, warns, errs := NewConfig(testConfig())
var c Config
warns, errs := c.Prepare(testConfig())
if len(warns) > 0 {
t.Fatalf("bad: %#v", len(warns))
}
@ -22,7 +23,7 @@ func testConfigStruct(t *testing.T) *Config {
t.Fatalf("bad: %#v", errs)
}
return c
return &c
}
func testConfigErr(t *testing.T, warns []string, err error) {
@ -55,17 +56,18 @@ func TestConfigPrepare_exportPath(t *testing.T) {
// No export path. This is invalid. Previously this would not error during
// validation and as a result the failure would happen at build time.
delete(raw, "export_path")
_, warns, errs := NewConfig(raw)
var c Config
warns, errs := c.Prepare(raw)
testConfigErr(t, warns, errs)
// Good export path
raw["export_path"] = "good"
_, warns, errs = NewConfig(raw)
warns, errs = c.Prepare(raw)
testConfigOk(t, warns, errs)
// Bad export path (directory)
raw["export_path"] = td
_, warns, errs = NewConfig(raw)
warns, errs = c.Prepare(raw)
testConfigErr(t, warns, errs)
}
@ -74,17 +76,17 @@ func TestConfigPrepare_exportPathAndCommit(t *testing.T) {
// Export but no commit (explicit default)
raw["commit"] = false
_, warns, errs := NewConfig(raw)
warns, errs := (&Config{}).Prepare(raw)
testConfigOk(t, warns, errs)
// Commit AND export specified (invalid)
raw["commit"] = true
_, warns, errs = NewConfig(raw)
warns, errs = (&Config{}).Prepare(raw)
testConfigErr(t, warns, errs)
// Commit but no export
delete(raw, "export_path")
_, warns, errs = NewConfig(raw)
warns, errs = (&Config{}).Prepare(raw)
testConfigOk(t, warns, errs)
}
@ -93,18 +95,18 @@ func TestConfigPrepare_exportDiscard(t *testing.T) {
// Export but no discard (explicit default)
raw["discard"] = false
_, warns, errs := NewConfig(raw)
warns, errs := (&Config{}).Prepare(raw)
testConfigOk(t, warns, errs)
// Discard AND export (invalid)
raw["discard"] = true
_, warns, errs = NewConfig(raw)
warns, errs = (&Config{}).Prepare(raw)
testConfigErr(t, warns, errs)
// Discard but no export
raw["discard"] = true
delete(raw, "export_path")
_, warns, errs = NewConfig(raw)
warns, errs = (&Config{}).Prepare(raw)
testConfigOk(t, warns, errs)
}
@ -113,12 +115,13 @@ func TestConfigPrepare_image(t *testing.T) {
// No image
delete(raw, "image")
_, warns, errs := NewConfig(raw)
var c Config
warns, errs := c.Prepare(raw)
testConfigErr(t, warns, errs)
// Good image
raw["image"] = "path"
_, warns, errs = NewConfig(raw)
warns, errs = c.Prepare(raw)
testConfigOk(t, warns, errs)
}
@ -127,7 +130,8 @@ func TestConfigPrepare_pull(t *testing.T) {
// No pull set
delete(raw, "pull")
c, warns, errs := NewConfig(raw)
var c Config
warns, errs := c.Prepare(raw)
testConfigOk(t, warns, errs)
if !c.Pull {
t.Fatal("should pull by default")
@ -135,7 +139,7 @@ func TestConfigPrepare_pull(t *testing.T) {
// Pull set
raw["pull"] = false
c, warns, errs = NewConfig(raw)
warns, errs = c.Prepare(raw)
testConfigOk(t, warns, errs)
if c.Pull {
t.Fatal("should not pull")

View File

@ -14,11 +14,17 @@ type StepCommit struct {
}
func (s *StepCommit) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
config, ok := state.Get("config").(*Config)
if !ok {
err := fmt.Errorf("error encountered obtaining docker config")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
driver := state.Get("driver").(Driver)
containerId := state.Get("container_id").(string)
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
if config.WindowsContainer {
// docker can't commit a running Windows container
err := driver.StopContainer(containerId)

View File

@ -12,7 +12,13 @@ import (
type StepConnectDocker struct{}
func (s *StepConnectDocker) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
config, ok := state.Get("config").(*Config)
if !ok {
err := fmt.Errorf("error encountered obtaining docker config")
state.Put("error", err)
return multistep.ActionHalt
}
containerId := state.Get("container_id").(string)
driver := state.Get("driver").(Driver)
tempDir := state.Get("temp_dir").(string)

View File

@ -14,11 +14,14 @@ import (
type StepExport struct{}
func (s *StepExport) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
driver := state.Get("driver").(Driver)
containerId := state.Get("container_id").(string)
ui := state.Get("ui").(packer.Ui)
config, ok := state.Get("config").(*Config)
if !ok {
err := fmt.Errorf("error encountered obtaining docker config")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
// We should catch this in validation, but guard anyway
if config.ExportPath == "" {
@ -44,6 +47,9 @@ func (s *StepExport) Run(ctx context.Context, state multistep.StateBag) multiste
return multistep.ActionHalt
}
driver := state.Get("driver").(Driver)
containerId := state.Get("container_id").(string)
ui.Say("Exporting the container")
if err := driver.Export(containerId, f); err != nil {
f.Close()

View File

@ -12,9 +12,14 @@ import (
type StepPull struct{}
func (s *StepPull) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)
config, ok := state.Get("config").(*Config)
if !ok {
err := fmt.Errorf("error encountered obtaining docker config")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if !config.Pull {
log.Println("Pull disabled, won't docker pull")
@ -38,6 +43,7 @@ func (s *StepPull) Run(ctx context.Context, state multistep.StateBag) multistep.
config.LoginPassword = password
}
driver := state.Get("driver").(Driver)
if config.Login || config.EcrLogin {
ui.Message("Logging in...")
err := driver.Login(

View File

@ -13,10 +13,14 @@ type StepRun struct {
}
func (s *StepRun) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
driver := state.Get("driver").(Driver)
tempDir := state.Get("temp_dir").(string)
ui := state.Get("ui").(packer.Ui)
config, ok := state.Get("config").(*Config)
if !ok {
err := fmt.Errorf("error encountered obtaining docker config")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
runConfig := ContainerConfig{
Image: config.Image,
@ -28,8 +32,11 @@ func (s *StepRun) Run(ctx context.Context, state multistep.StateBag) multistep.S
for host, container := range config.Volumes {
runConfig.Volumes[host] = container
}
tempDir := state.Get("temp_dir").(string)
runConfig.Volumes[tempDir] = config.ContainerDir
driver := state.Get("driver").(Driver)
ui.Say("Starting docker container...")
containerId, err := driver.StartContainer(&runConfig)
if err != nil {
@ -42,6 +49,9 @@ func (s *StepRun) Run(ctx context.Context, state multistep.StateBag) multistep.S
// Save the container ID
s.containerId = containerId
state.Put("container_id", s.containerId)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", s.containerId)
ui.Message(fmt.Sprintf("Container ID: %s", s.containerId))
return multistep.ActionContinue
}

View File

@ -12,6 +12,7 @@ import (
"io/ioutil"
"os"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
@ -19,18 +20,19 @@ import (
const BuilderId = "packer.file"
type Builder struct {
config *Config
config Config
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
c, warnings, errs := NewConfig(raws...)
if errs != nil {
return warnings, errs
}
b.config = c
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
return warnings, nil
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
warnings, errs := b.config.Prepare(raws...)
if errs != nil {
return nil, warnings, errs
}
return nil, warnings, nil
}
// Run is where the actual build should take place. It takes a Build and a Ui.

View File

@ -22,8 +22,7 @@ type Config struct {
Content string `mapstructure:"content"`
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
c := new(Config)
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
warnings := []string{}
err := config.Decode(c, &config.DecodeOpts{
@ -33,7 +32,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
},
}, raws...)
if err != nil {
return nil, warnings, err
return warnings, err
}
var errs *packer.MultiError
@ -51,8 +50,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return nil, warnings, errs
return warnings, errs
}
return c, warnings, nil
return warnings, nil
}

View File

@ -24,10 +24,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},

View File

@ -16,7 +16,8 @@ func testConfig() map[string]interface{} {
func TestContentSourceConflict(t *testing.T) {
raw := testConfig()
_, _, errs := NewConfig(raw)
var c Config
_, errs := c.Prepare(raw)
if !strings.Contains(errs.Error(), ErrContentSourceConflict.Error()) {
t.Errorf("Expected config error: %s", ErrContentSourceConflict.Error())
}
@ -26,7 +27,8 @@ func TestNoFilename(t *testing.T) {
raw := testConfig()
delete(raw, "filename")
_, _, errs := NewConfig(raw)
var c Config
_, errs := c.Prepare(raw)
if errs == nil {
t.Errorf("Expected config error: %s", ErrTargetRequired.Error())
}
@ -37,7 +39,8 @@ func TestNoContent(t *testing.T) {
delete(raw, "content")
delete(raw, "source")
_, warns, _ := NewConfig(raw)
var c Config
warns, _ := c.Prepare(raw)
if len(warns) == 0 {
t.Error("Expected config warning without any content")

View File

@ -7,6 +7,7 @@ import (
"fmt"
"log"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
@ -18,18 +19,18 @@ const BuilderId = "packer.googlecompute"
// Builder represents a Packer Builder.
type Builder struct {
config *Config
config Config
runner multistep.Runner
}
// Prepare processes the build configuration parameters.
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
c, warnings, errs := NewConfig(raws...)
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
warnings, errs := b.config.Prepare(raws...)
if errs != nil {
return warnings, errs
return nil, warnings, errs
}
b.config = c
return warnings, nil
return nil, warnings, nil
}
// Run executes a googlecompute Packer build and returns a packer.Artifact
@ -43,7 +44,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
// Set up the state.
state := new(multistep.BasicStateBag)
state.Put("config", b.config)
state.Put("config", &b.config)
state.Put("driver", driver)
state.Put("hook", hook)
state.Put("ui", ui)
@ -97,7 +98,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
artifact := &Artifact{
image: state.Get("image").(*Image),
driver: driver,
config: b.config,
config: &b.config,
}
return artifact, nil
}

View File

@ -187,8 +187,7 @@ type Config struct {
ctx interpolate.Context
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
c := new(Config)
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
c.ctx.Funcs = TemplateFuncs
err := config.Decode(c, &config.DecodeOpts{
Interpolate: true,
@ -200,7 +199,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
},
}, raws...)
if err != nil {
return nil, nil, err
return nil, err
}
var errs *packer.MultiError
@ -372,10 +371,10 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
// Check for any errors.
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
return nil, errs
}
return c, nil, nil
return nil, nil
}
type CustomerEncryptionKey struct {

View File

@ -46,8 +46,8 @@ type FlatConfig struct {
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
@ -100,10 +100,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
@ -206,10 +209,13 @@ type FlatCustomerEncryptionKey struct {
// FlatMapstructure returns a new FlatCustomerEncryptionKey.
// FlatCustomerEncryptionKey is an auto-generated flat version of CustomerEncryptionKey.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*CustomerEncryptionKey) FlatMapstructure() interface{} { return new(FlatCustomerEncryptionKey) }
func (*CustomerEncryptionKey) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatCustomerEncryptionKey)
}
// HCL2Spec returns the hcldec.Spec of a FlatCustomerEncryptionKey.
// This spec is used by HCL to read the fields of FlatCustomerEncryptionKey.
// HCL2Spec returns the hcl spec of a CustomerEncryptionKey.
// This spec is used by HCL to read the fields of CustomerEncryptionKey.
// The decoded values from this spec will then be applied to a FlatCustomerEncryptionKey.
func (*FlatCustomerEncryptionKey) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"kms_key_name": &hcldec.AttrSpec{Name: "kms_key_name", Type: cty.String, Required: false},

View File

@ -242,7 +242,8 @@ func TestConfigPrepare(t *testing.T) {
raw[tc.Key] = tc.Value
}
_, warns, errs := NewConfig(raw)
var c Config
warns, errs := c.Prepare(raw)
if tc.Err {
testConfigErr(t, warns, errs, tc.Key)
@ -302,7 +303,8 @@ func TestConfigPrepareAccelerator(t *testing.T) {
}
}
_, warns, errs := NewConfig(raw)
var c Config
warns, errs := c.Prepare(raw)
if tc.Err {
testConfigErr(t, warns, errs, strings.TrimRight(errStr, ", "))
@ -352,7 +354,8 @@ func TestConfigPrepareServiceAccount(t *testing.T) {
}
}
_, warns, errs := NewConfig(raw)
var c Config
warns, errs := c.Prepare(raw)
if tc.Err {
testConfigErr(t, warns, errs, strings.TrimRight(errStr, ", "))
@ -371,7 +374,8 @@ func TestConfigPrepareStartupScriptFile(t *testing.T) {
"zone": "us-central1-a",
}
_, _, errs := NewConfig(config)
var c Config
_, errs := c.Prepare(config)
if errs == nil || !strings.Contains(errs.Error(), "startup_script_file") {
t.Fatalf("should error: startup_script_file")
@ -398,10 +402,11 @@ func TestConfigDefaults(t *testing.T) {
raw, tempfile := testConfig(t)
defer os.Remove(tempfile)
c, warns, errs := NewConfig(raw)
var c Config
warns, errs := c.Prepare(raw)
testConfigOk(t, warns, errs)
actual := tc.Read(c)
actual := tc.Read(&c)
if actual != tc.Value {
t.Fatalf("bad: %#v", actual)
}
@ -412,7 +417,8 @@ func TestImageName(t *testing.T) {
raw, tempfile := testConfig(t)
defer os.Remove(tempfile)
c, _, _ := NewConfig(raw)
var c Config
c.Prepare(raw)
if !strings.HasPrefix(c.ImageName, "packer-") {
t.Fatalf("ImageName should have 'packer-' prefix, found %s", c.ImageName)
}
@ -425,7 +431,8 @@ func TestRegion(t *testing.T) {
raw, tempfile := testConfig(t)
defer os.Remove(tempfile)
c, _, _ := NewConfig(raw)
var c Config
c.Prepare(raw)
if c.Region != "us-east1" {
t.Fatalf("Region should be 'us-east1' given Zone of 'us-east1-a', but is %s", c.Region)
}
@ -460,7 +467,8 @@ func testConfigStruct(t *testing.T) *Config {
raw, tempfile := testConfig(t)
defer os.Remove(tempfile)
c, warns, errs := NewConfig(raw)
var c Config
warns, errs := c.Prepare(raw)
if len(warns) > 0 {
t.Fatalf("bad: %#v", len(warns))
}
@ -468,7 +476,7 @@ func testConfigStruct(t *testing.T) *Config {
t.Fatalf("bad: %#v", errs)
}
return c
return &c
}
func testConfigErr(t *testing.T, warns []string, err error, extra string) {

View File

@ -176,6 +176,9 @@ func (s *StepCreateInstance) Run(ctx context.Context, state multistep.StateBag)
// Things succeeded, store the name so we can remove it later
state.Put("instance_name", name)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", name)
return multistep.ActionContinue
}

View File

@ -13,7 +13,6 @@ import (
"os"
"time"
commonhelper "github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
@ -119,7 +118,6 @@ func (s *StepCreateWindowsPassword) Run(ctx context.Context, state multistep.Sta
}
state.Put("winrm_password", data.password)
commonhelper.SetSharedState("winrm_password", data.password, c.PackerConfig.PackerBuildName)
packer.LogSecretFilter.Set(data.password)
return multistep.ActionContinue

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
@ -22,13 +23,15 @@ type Builder struct {
var pluginVersion = "1.0.0"
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
config, warnings, errs := NewConfig(raws...)
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
warnings, errs := b.config.Prepare(raws...)
if errs != nil {
return warnings, errs
return nil, warnings, errs
}
b.config = *config
return nil, nil
return nil, nil, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {

View File

@ -50,9 +50,7 @@ type imageFilter struct {
MostRecent bool `mapstructure:"most_recent"`
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
c := new(Config)
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
var md mapstructure.Metadata
err := config.Decode(c, &config.DecodeOpts{
Metadata: &md,
@ -65,7 +63,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
},
}, raws...)
if err != nil {
return nil, nil, err
return nil, err
}
// Defaults
@ -142,11 +140,11 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
return nil, errs
}
packer.LogSecretFilter.Set(c.HCloudToken)
return c, nil, nil
return nil, nil
}
func getServerIP(state multistep.StateBag) (string, error) {

View File

@ -46,8 +46,8 @@ type FlatConfig struct {
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
@ -75,10 +75,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
@ -156,10 +159,13 @@ type FlatimageFilter struct {
// FlatMapstructure returns a new FlatimageFilter.
// FlatimageFilter is an auto-generated flat version of imageFilter.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*imageFilter) FlatMapstructure() interface{} { return new(FlatimageFilter) }
func (*imageFilter) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatimageFilter)
}
// HCL2Spec returns the hcldec.Spec of a FlatimageFilter.
// This spec is used by HCL to read the fields of FlatimageFilter.
// HCL2Spec returns the hcl spec of a imageFilter.
// This spec is used by HCL to read the fields of imageFilter.
// The decoded values from this spec will then be applied to a FlatimageFilter.
func (*FlatimageFilter) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"with_selector": &hcldec.AttrSpec{Name: "with_selector", Type: cty.List(cty.String), Required: false},

View File

@ -85,6 +85,9 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu
// Store the server id for later
state.Put("server_id", serverCreateResult.Server.ID)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", serverCreateResult.Server.ID)
if err := waitForAction(ctx, client, serverCreateResult.Action); err != nil {
err := fmt.Errorf("Error creating server: %s", err)

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
@ -20,13 +21,13 @@ type Builder struct {
client *openapi.APIClient
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
config, warnings, errs := NewConfig(raws...)
if errs != nil {
return warnings, errs
}
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
b.config = *config
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
warnings, errs := b.config.Prepare(raws...)
if errs != nil {
return nil, warnings, errs
}
cfg := openapi.NewConfiguration()
cfg.AddDefaultHeader("x-auth-token", b.config.Token)
@ -43,7 +44,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
b.client = openapi.NewAPIClient(cfg)
return nil, nil
return nil, nil, nil
}
type wrappedCommandTemplate struct {

View File

@ -114,8 +114,7 @@ type Config struct {
ctx interpolate.Context
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
c := &Config{}
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
var md mapstructure.Metadata
err := config.Decode(c, &config.DecodeOpts{
@ -133,12 +132,12 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
},
}, raws...)
if err != nil {
return nil, nil, err
return nil, err
}
cliConfig, err := loadCLIConfig()
if err != nil {
return nil, nil, err
return nil, err
}
// Defaults
@ -165,7 +164,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
if c.TokenLogin != "" && c.APIURL == "" {
c.Token, err = fetchTokenBySSH(c.TokenLogin)
if err != nil {
return nil, nil, err
return nil, err
}
}
}
@ -181,7 +180,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
if c.ImageName == "" {
name, err := interpolate.Render("packer-{{timestamp}}", nil)
if err != nil {
return nil, nil, err
return nil, err
}
c.ImageName = name
}
@ -217,7 +216,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
if c.ChrootMountPath == "" {
path, err := interpolate.Render("/mnt/packer-hyperone-volumes/{{timestamp}}", nil)
if err != nil {
return nil, nil, err
return nil, err
}
c.ChrootMountPath = path
}
@ -281,12 +280,12 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
return nil, errs
}
packer.LogSecretFilter.Set(c.Token)
return c, nil, nil
return nil, nil
}
type cliConfig struct {

View File

@ -46,8 +46,8 @@ type FlatConfig struct {
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
@ -94,10 +94,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},

View File

@ -67,6 +67,9 @@ func (s *stepCreateVM) Run(ctx context.Context, state multistep.StateBag) multis
s.vmID = vm.Id
state.Put("vm_id", vm.Id)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", vm.Id)
hdds, _, err := client.VmApi.VmListHdd(ctx, vm.Id)
if err != nil {

View File

@ -15,10 +15,13 @@ type FlatOutputConfig struct {
// FlatMapstructure returns a new FlatOutputConfig.
// FlatOutputConfig is an auto-generated flat version of OutputConfig.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*OutputConfig) FlatMapstructure() interface{} { return new(FlatOutputConfig) }
func (*OutputConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatOutputConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatOutputConfig.
// This spec is used by HCL to read the fields of FlatOutputConfig.
// HCL2Spec returns the hcl spec of a OutputConfig.
// This spec is used by HCL to read the fields of OutputConfig.
// The decoded values from this spec will then be applied to a FlatOutputConfig.
func (*FlatOutputConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},

View File

@ -154,6 +154,9 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist
// Set the final name in the state bag so others can use it
state.Put("vmName", s.VMName)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", s.VMName)
return multistep.ActionContinue
}

View File

@ -166,6 +166,9 @@ func (s *StepCreateVM) Run(ctx context.Context, state multistep.StateBag) multis
// Set the final name in the state bag so others can use it
state.Put("vmName", s.VMName)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", s.VMName)
return multistep.ActionContinue
}

View File

@ -11,6 +11,7 @@ import (
"path/filepath"
"strings"
"github.com/hashicorp/hcl/v2/hcldec"
hypervcommon "github.com/hashicorp/packer/builder/hyperv/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/common/bootcommand"
@ -84,8 +85,9 @@ type Config struct {
ctx interpolate.Context
}
// Prepare processes the build configuration parameters.
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
err := config.Decode(&b.config, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &b.config.ctx,
@ -96,7 +98,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
},
}, raws...)
if err != nil {
return nil, err
return nil, nil, err
}
// Accumulate any errors and warnings
@ -164,10 +166,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return warnings, errs
return nil, warnings, errs
}
return warnings, nil
return nil, warnings, nil
}
// Run executes a Packer build and returns a packer.Artifact representing
@ -181,7 +183,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
// Set up the state.
state := new(multistep.BasicStateBag)
state.Put("config", &b.config)
state.Put("debug", b.config.PackerDebug)
state.Put("driver", driver)
state.Put("hook", hook)

View File

@ -60,8 +60,8 @@ type FlatConfig struct {
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
@ -108,10 +108,13 @@ type FlatConfig struct {
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{} { return new(FlatConfig) }
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcldec.Spec of a FlatConfig.
// This spec is used by HCL to read the fields of FlatConfig.
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},

View File

@ -42,7 +42,7 @@ func TestBuilderPrepare_Defaults(t *testing.T) {
var b Builder
config := testConfig()
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -60,7 +60,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) {
config := testConfig()
delete(config, "disk_size")
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -74,7 +74,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) {
config["disk_size"] = 256
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -96,7 +96,7 @@ func TestBuilderPrepare_DiskBlockSize(t *testing.T) {
// Test default with empty disk_block_size
delete(config, "disk_block_size")
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -112,7 +112,7 @@ func TestBuilderPrepare_DiskBlockSize(t *testing.T) {
for _, test_size := range test_sizes {
config["disk_block_size"] = test_size
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if test_size > expected_max_block_size || test_size < expected_min_block_size {
if len(warns) > 0 {
t.Fatalf("bad, should have no warns: %#v", warns)
@ -153,7 +153,7 @@ func TestBuilderPrepare_FixedVHDFormat(t *testing.T) {
// use_fixed_vhd_format should work with generation = 1, skip_compaction
// = true, and differencing_disk = false
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -164,7 +164,7 @@ func TestBuilderPrepare_FixedVHDFormat(t *testing.T) {
//use_fixed_vhd_format should not work with differencing_disk = true
config["differencing_disk"] = true
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -176,7 +176,7 @@ func TestBuilderPrepare_FixedVHDFormat(t *testing.T) {
//use_fixed_vhd_format should not work with skip_compaction = false
config["skip_compaction"] = false
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -188,7 +188,7 @@ func TestBuilderPrepare_FixedVHDFormat(t *testing.T) {
//use_fixed_vhd_format should not work with generation = 2
config["generation"] = 2
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -202,7 +202,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) {
config := testConfig()
delete(config, "floppy_files")
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -217,7 +217,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) {
floppiesPath := "../../../common/test-fixtures/floppies"
config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppiesPath), fmt.Sprintf("%s/foo.ps1", floppiesPath)}
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -236,7 +236,7 @@ func TestBuilderPrepare_InvalidFloppies(t *testing.T) {
config := testConfig()
config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"}
b = Builder{}
_, errs := b.Prepare(config)
_, _, errs := b.Prepare(config)
if errs == nil {
t.Fatalf("Nonexistent floppies should trigger multierror")
}
@ -252,7 +252,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -267,7 +267,7 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) {
// Test bad
config["iso_checksum"] = ""
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -278,7 +278,7 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) {
// Test good
config["iso_checksum"] = "FOo"
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -294,7 +294,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test bad
config["iso_checksum_type"] = ""
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -305,7 +305,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test good
config["iso_checksum_type"] = "mD5"
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -320,7 +320,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test unknown
config["iso_checksum_type"] = "fake"
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -331,7 +331,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test none
config["iso_checksum_type"] = "none"
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) == 0 {
t.Fatalf("bad: %#v", warns)
}
@ -353,7 +353,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
// Test both empty
config["iso_url"] = ""
b = Builder{}
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -364,7 +364,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
// Test iso_url set
config["iso_url"] = "http://www.packer.io"
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -381,7 +381,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
config["iso_url"] = "http://www.packer.io"
config["iso_urls"] = []string{"http://www.packer.io"}
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -397,7 +397,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
}
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -431,7 +431,7 @@ func TestBuilderPrepare_SizeNotRequiredWhenUsingExistingHarddrive(t *testing.T)
}
b = Builder{}
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -455,7 +455,7 @@ func TestBuilderPrepare_SizeNotRequiredWhenUsingExistingHarddrive(t *testing.T)
}
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -489,7 +489,7 @@ func TestBuilderPrepare_SizeIsRequiredWhenNotUsingExistingHarddrive(t *testing.T
}
b = Builder{}
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -517,7 +517,7 @@ func TestBuilderPrepare_MaximumOfSixtyFourAdditionalDisks(t *testing.T) {
config["disk_additional_size"] = disks
b = Builder{}
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -537,7 +537,7 @@ func TestBuilderPrepare_CommConfig(t *testing.T) {
config["winrm_host"] = "1.2.3.4"
var b Builder
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -565,7 +565,7 @@ func TestBuilderPrepare_CommConfig(t *testing.T) {
config["ssh_host"] = "1.2.3.4"
var b Builder
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -593,7 +593,7 @@ func TestUserVariablesInBootCommand(t *testing.T) {
config[packer.UserVariablesConfigKey] = map[string]string{"test-variable": "test"}
config["boot_command"] = []string{"blah {{user `test-variable`}} blah"}
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -634,7 +634,7 @@ func TestBuilderPrepare_UseLegacyNetworkAdapter(t *testing.T) {
config["use_legacy_network_adapter"] = true
b = Builder{}
warns, err := b.Prepare(config)
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
@ -646,7 +646,7 @@ func TestBuilderPrepare_UseLegacyNetworkAdapter(t *testing.T) {
config["generation"] = 2
b = Builder{}
warns, err = b.Prepare(config)
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}

View File

@ -10,6 +10,7 @@ import (
"os"
"strings"
"github.com/hashicorp/hcl/v2/hcldec"
hypervcommon "github.com/hashicorp/packer/builder/hyperv/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/common/bootcommand"
@ -77,8 +78,9 @@ type Config struct {
ctx interpolate.Context
}
// Prepare processes the build configuration parameters.
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
err := config.Decode(&b.config, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &b.config.ctx,
@ -89,7 +91,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
},
}, raws...)
if err != nil {
return nil, err
return nil, nil, err
}
// Accumulate any errors and warnings
@ -204,10 +206,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
if errs != nil && len(errs.Errors) > 0 {
return warnings, errs
return nil, warnings, errs
}
return warnings, nil
return nil, warnings, nil
}
// Run executes a Packer build and returns a packer.Artifact representing
@ -221,7 +223,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
// Set up the state.
state := new(multistep.BasicStateBag)
state.Put("config", &b.config)
state.Put("debug", b.config.PackerDebug)
state.Put("driver", driver)
state.Put("hook", hook)
@ -235,23 +236,15 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Force: b.config.PackerForce,
Path: b.config.OutputDir,
},
}
if b.config.RawSingleISOUrl != "" || len(b.config.ISOUrls) > 0 {
steps = append(steps,
&common.StepDownload{
Checksum: b.config.ISOChecksum,
ChecksumType: b.config.ISOChecksumType,
Description: "ISO",
ResultKey: "iso_path",
Url: b.config.ISOUrls,
Extension: b.config.TargetExtension,
TargetPath: b.config.TargetPath,
},
)
}
steps = append(steps,
&common.StepDownload{
Checksum: b.config.ISOChecksum,
ChecksumType: b.config.ISOChecksumType,
Description: "ISO",
ResultKey: "iso_path",
Url: b.config.ISOUrls,
Extension: b.config.TargetExtension,
TargetPath: b.config.TargetPath,
},
&common.StepCreateFloppy{
Files: b.config.FloppyFiles,
Directories: b.config.FloppyConfig.FloppyDirectories,
@ -366,9 +359,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
OutputDir: b.config.OutputDir,
SkipExport: b.config.SkipExport,
},
}
// the clean up actions for each step will be executed reverse order
)
// the clean up actions for each step will be executed reverse order
// Run the steps.
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)

Some files were not shown because too many files have changed in this diff Show More