mirror of
https://github.com/hashicorp/packer.git
synced 2026-06-11 01:30:06 -04:00
Merge branch 'master' into feature/vgpu-profiles
This commit is contained in:
commit
ebfc5bcdcb
736 changed files with 79127 additions and 118483 deletions
|
|
@ -80,9 +80,9 @@ jobs:
|
|||
check-lint:
|
||||
executor: golang
|
||||
resource_class: large
|
||||
working_directory: /go/src/github.com/hashicorp/packer
|
||||
steps:
|
||||
- checkout
|
||||
- run: git fetch --all
|
||||
- run:
|
||||
command: make ci-lint
|
||||
no_output_timeout: 30m
|
||||
|
|
|
|||
1
.gitattributes
vendored
1
.gitattributes
vendored
|
|
@ -3,6 +3,7 @@
|
|||
*.sh text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.mdx text eol=lf
|
||||
*.ps1 text eol=lf
|
||||
*.hcl text eol=lf
|
||||
go.mod text eol=lf
|
||||
|
|
|
|||
|
|
@ -3,12 +3,19 @@
|
|||
**New Builder** azure-dtl allows creation of devtestlabs images in Azure. [GH-8987]
|
||||
|
||||
### IMPROVEMENTS:
|
||||
* builder/azure: Add shared image destination for azure-chroot [GH-9021]
|
||||
* builder/azure: Data disk names are now randomly generated [GH-8986]
|
||||
* builder/google: Allow `source_image_project_id` to be a list of several
|
||||
projects to search. [GH-8679]
|
||||
* builder/oracle-oci: Allow Instance Principal Auth for Oracle OCI builder
|
||||
[GH-8893]
|
||||
* core/hcl2: Set `packer_build_name` and `packer_builder_type` variables for
|
||||
builder provisioners and post-processors [GH-8956]
|
||||
* provisioner/ansible: Add option to not use localhost proxy adapter. Removes
|
||||
need for ansible connection_plugin when using WinRM. [GH-8625]
|
||||
* provisioner/powershell: Add cleanup step to remove temporarily created
|
||||
scripts; cleanup can be skipped by setting the `skip_clean` option
|
||||
[GH-8908]
|
||||
|
||||
### Bug Fixes:
|
||||
* builder/amazon: Fix bug with launch_block_device_mappings in spot instances.
|
||||
|
|
@ -18,6 +25,8 @@
|
|||
* builder/qemu: Remove `net_device` pre-validation [GH-8979]
|
||||
* builder/vsphere-iso: disk_size is no longer required if storage is defined
|
||||
[GH-8975]
|
||||
* core: Fix crash in wrapperreadline helper when calling `os.NewFile` on
|
||||
unknown file descriptor [GH-9037]
|
||||
* core: Make sure CLI variables supersede variables from var files [GH-8964]
|
||||
* provisioner/powershell: Fix integer decoding issue in the execution policy
|
||||
parser [GH-8997]
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
/builder/jdcloud/ @XiaohanLiang @remrain
|
||||
/website/pages/docs/builders/jdcloud* @XiaohanLiang @remrain
|
||||
|
||||
/builder/linode/ @displague @ctreatma @stvnjacobs
|
||||
/website/pages/docs/builders/linode* @displague @ctreatma @stvnjacobs
|
||||
/builder/linode/ @displague @ctreatma @stvnjacobs @charliekenney23 @phillc
|
||||
/website/pages/docs/builders/linode* @displague @ctreatma @stvnjacobs @charliekenney23 @phillc
|
||||
|
||||
/builder/lxc/ @ChrisLundquist
|
||||
/website/pages/docs/builders/lxc* @ChrisLundquist
|
||||
|
|
@ -59,6 +59,10 @@
|
|||
/builder/osc/ @marinsalinas
|
||||
/website/pages/docs/builders/osc* @marinsalinas
|
||||
|
||||
/builder/tencentcloud/ @likexian
|
||||
/website/pages/docs/builders/tencentcloud* @likexian
|
||||
|
||||
|
||||
|
||||
# provisioners
|
||||
|
||||
|
|
|
|||
7
Makefile
7
Makefile
|
|
@ -16,7 +16,9 @@ EXECUTABLE_FILES=$(shell find . -type f -executable | egrep -v '^\./(website/[ve
|
|||
GIT_DIRTY=$(shell test -n "`git status --porcelain`" && echo "+CHANGES" || true)
|
||||
GIT_COMMIT=$(shell git rev-parse --short HEAD)
|
||||
GIT_IMPORT=github.com/hashicorp/packer/version
|
||||
GOLDFLAGS=-X $(GIT_IMPORT).GitCommit=$(GIT_COMMIT)$(GIT_DIRTY)
|
||||
UNAME_S := $(shell uname -s)
|
||||
LDFLAGS=-s -w
|
||||
GOLDFLAGS=-X $(GIT_IMPORT).GitCommit=$(GIT_COMMIT)$(GIT_DIRTY) $(LDFLAGS)
|
||||
|
||||
export GOLDFLAGS
|
||||
|
||||
|
|
@ -84,8 +86,7 @@ lint: install-lint-deps ## Lint Go code
|
|||
|
||||
ci-lint: install-lint-deps ## On ci only lint newly added Go source files
|
||||
@echo "==> Running linter on newly added Go source files..."
|
||||
GO111MODULE=on golangci-lint run --new-from-rev=`git merge-base master HEAD` ./...
|
||||
|
||||
@GO111MODULE=on sh -c "$(CURDIR)/scripts/lint.sh"
|
||||
|
||||
fmt: ## Format Go code
|
||||
@go fmt ./...
|
||||
|
|
|
|||
35
appveyor.yml
35
appveyor.yml
|
|
@ -1,35 +0,0 @@
|
|||
# appveyor.yml reference : http://www.appveyor.com/docs/appveyor-yml
|
||||
|
||||
version: "{build}"
|
||||
|
||||
skip_tags: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
os: Windows Server 2012 R2
|
||||
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\hashicorp\packer
|
||||
|
||||
install:
|
||||
- set GO111MODULE=off
|
||||
- echo %Path%
|
||||
- go version
|
||||
- go env
|
||||
|
||||
build_script:
|
||||
- git rev-parse HEAD
|
||||
# go test $(go list ./... | grep -v vendor)
|
||||
- ps: |
|
||||
go.exe test -timeout=2m (go.exe list ./... `
|
||||
|? { -not $_.Contains('/vendor/') } `
|
||||
|? { $_ -ne 'github.com/hashicorp/packer/builder/parallels/common' } `
|
||||
|? { $_ -ne 'github.com/hashicorp/packer/provisioner/ansible' })
|
||||
|
||||
test: off
|
||||
|
||||
deploy: off
|
||||
|
|
@ -160,7 +160,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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},
|
||||
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
|
||||
|
|
@ -182,7 +182,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"image_force_delete_snapshots": &hcldec.AttrSpec{Name: "image_force_delete_snapshots", Type: cty.Bool, Required: false},
|
||||
"image_force_delete_instances": &hcldec.AttrSpec{Name: "image_force_delete_instances", Type: cty.Bool, Required: false},
|
||||
"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},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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.ObjectSpec((*FlatAlicloudDiskDevice)(nil).HCL2Spec())},
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
@ -101,7 +101,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: "tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
|
||||
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
|
||||
|
|
@ -109,9 +109,9 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(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_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -144,7 +144,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: "root_volume_tags", ElementType: cty.String, Required: false},
|
||||
"root_volume_tags": &hcldec.AttrSpec{Name: "root_volume_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"root_volume_tag": &hcldec.BlockListSpec{TypeName: "root_volume_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"ami_architecture": &hcldec.AttrSpec{Name: "ami_architecture", Type: cty.String, Required: false},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ func (*AmiFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcl
|
|||
// 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},
|
||||
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
|
||||
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"owners": &hcldec.AttrSpec{Name: "owners", Type: cty.List(cty.String), Required: false},
|
||||
"most_recent": &hcldec.AttrSpec{Name: "most_recent", Type: cty.Bool, Required: false},
|
||||
|
|
@ -80,7 +80,7 @@ func (*SecurityGroupFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[
|
|||
// 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},
|
||||
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
|
||||
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
|
|
@ -134,7 +134,7 @@ func (*SubnetFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]
|
|||
// 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},
|
||||
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
|
||||
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"most_free": &hcldec.AttrSpec{Name: "most_free", Type: cty.Bool, Required: false},
|
||||
"random": &hcldec.AttrSpec{Name: "random", Type: cty.Bool, Required: false},
|
||||
|
|
@ -161,7 +161,7 @@ func (*VpcFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcl
|
|||
// 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},
|
||||
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
|
||||
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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},
|
||||
|
|
@ -170,7 +170,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: "tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
|
||||
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
|
||||
|
|
@ -178,9 +178,9 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(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_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -196,7 +196,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"run_tags": &hcldec.AttrSpec{Name: "run_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_tag": &hcldec.BlockListSpec{TypeName: "run_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -205,7 +205,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"spot_tags": &hcldec.AttrSpec{Name: "spot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -259,7 +259,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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())},
|
||||
"run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "run_volume_tags", ElementType: cty.String, Required: false},
|
||||
"run_volume_tags": &hcldec.AttrSpec{Name: "run_volume_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"no_ephemeral": &hcldec.AttrSpec{Name: "no_ephemeral", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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},
|
||||
|
|
@ -219,7 +219,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"run_tags": &hcldec.AttrSpec{Name: "run_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_tag": &hcldec.BlockListSpec{TypeName: "run_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -228,7 +228,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"spot_tags": &hcldec.AttrSpec{Name: "spot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -287,7 +287,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: "tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
|
||||
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
|
||||
|
|
@ -295,16 +295,16 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(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_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"run_volume_tags": &hcldec.AttrSpec{Name: "run_volume_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"ami_architecture": &hcldec.AttrSpec{Name: "ami_architecture", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
|
|
@ -173,7 +173,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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},
|
||||
|
|
@ -200,7 +200,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"run_tags": &hcldec.AttrSpec{Name: "run_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_tag": &hcldec.BlockListSpec{TypeName: "run_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -209,7 +209,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"spot_tags": &hcldec.AttrSpec{Name: "spot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -264,7 +264,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"run_volume_tags": &hcldec.AttrSpec{Name: "run_volume_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_volume_tag": &hcldec.BlockListSpec{TypeName: "run_volume_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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},
|
||||
|
|
@ -177,7 +177,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: "tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
|
||||
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
|
||||
|
|
@ -185,9 +185,9 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(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_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -203,7 +203,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"run_tags": &hcldec.AttrSpec{Name: "run_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_tag": &hcldec.BlockListSpec{TypeName: "run_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
@ -212,7 +212,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"spot_tags": &hcldec.AttrSpec{Name: "spot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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},
|
||||
|
|
@ -163,7 +163,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"managed_image_os_disk_snapshot_name": &hcldec.AttrSpec{Name: "managed_image_os_disk_snapshot_name", Type: cty.String, Required: false},
|
||||
"managed_image_data_disk_snapshot_prefix": &hcldec.AttrSpec{Name: "managed_image_data_disk_snapshot_prefix", Type: cty.String, Required: false},
|
||||
"managed_image_zone_resilient": &hcldec.AttrSpec{Name: "managed_image_zone_resilient", Type: cty.Bool, Required: false},
|
||||
"azure_tags": &hcldec.BlockAttrsSpec{TypeName: "azure_tags", ElementType: cty.String, Required: false},
|
||||
"azure_tags": &hcldec.AttrSpec{Name: "azure_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"azure_tag": &hcldec.BlockListSpec{TypeName: "azure_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"resource_group_name": &hcldec.AttrSpec{Name: "resource_group_name", Type: cty.String, Required: false},
|
||||
"storage_account": &hcldec.AttrSpec{Name: "storage_account", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ import (
|
|||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
)
|
||||
|
||||
// BuilderId is the unique ID for this builder
|
||||
const BuilderId = "azure.chroot"
|
||||
// BuilderID is the unique ID for this builder
|
||||
const BuilderID = "azure.chroot"
|
||||
|
||||
// Config is the configuration that is chained through the steps and settable
|
||||
// from the template.
|
||||
|
|
@ -76,9 +76,6 @@ type Config struct {
|
|||
// `/etc/resolv.conf`. You may need to do this if you're building an image that uses systemd.
|
||||
CopyFiles []string `mapstructure:"copy_files"`
|
||||
|
||||
// The name of the temporary disk that will be created in the resource group of the VM that Packer is
|
||||
// running on. Will be generated if not set.
|
||||
TemporaryOSDiskName string `mapstructure:"temporary_os_disk_name"`
|
||||
// Try to resize the OS disk to this size on the first copy. Disks can only be englarged. If not specified,
|
||||
// the disk will keep its original size. Required when using `from_scratch`
|
||||
OSDiskSizeGB int32 `mapstructure:"os_disk_size_gb"`
|
||||
|
|
@ -88,15 +85,25 @@ type Config struct {
|
|||
// The [cache type](https://docs.microsoft.com/en-us/rest/api/compute/images/createorupdate#cachingtypes)
|
||||
// specified in the resulting image and for attaching it to the Packer VM. Defaults to `ReadOnly`
|
||||
OSDiskCacheType string `mapstructure:"os_disk_cache_type"`
|
||||
// If set to `true`, leaves the temporary disk behind in the Packer VM resource group. Defaults to `false`
|
||||
OSDiskSkipCleanup bool `mapstructure:"os_disk_skip_cleanup"`
|
||||
|
||||
// The image to create using this build.
|
||||
ImageResourceID string `mapstructure:"image_resource_id" required:"true"`
|
||||
// The [Hyper-V generation type](https://docs.microsoft.com/en-us/rest/api/compute/images/createorupdate#hypervgenerationtypes).
|
||||
// The [Hyper-V generation type](https://docs.microsoft.com/en-us/rest/api/compute/images/createorupdate#hypervgenerationtypes) for Managed Image output.
|
||||
// Defaults to `V1`.
|
||||
ImageHyperVGeneration string `mapstructure:"image_hyperv_generation"`
|
||||
|
||||
// The id of the temporary disk that will be created. Will be generated if not set.
|
||||
TemporaryOSDiskID string `mapstructure:"temporary_os_disk_id"`
|
||||
|
||||
// The id of the temporary snapshot that will be created. Will be generated if not set.
|
||||
TemporaryOSDiskSnapshotID string `mapstructure:"temporary_os_disk_snapshot_id"`
|
||||
|
||||
// If set to `true`, leaves the temporary disks and snapshots behind in the Packer VM resource group. Defaults to `false`
|
||||
SkipCleanup bool `mapstructure:"skip_cleanup"`
|
||||
|
||||
// The managed image to create using this build.
|
||||
ImageResourceID string `mapstructure:"image_resource_id"`
|
||||
|
||||
// The shared image to create using this build.
|
||||
SharedImageGalleryDestination SharedImageGalleryDestination `mapstructure:"shared_image_destination"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
|
|
@ -118,11 +125,15 @@ type Builder struct {
|
|||
runner multistep.Runner
|
||||
}
|
||||
|
||||
// verify interface implementation
|
||||
var _ packer.Builder = &Builder{}
|
||||
|
||||
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()
|
||||
md := &mapstructure.Metadata{}
|
||||
err := config.Decode(&b.config, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &b.config.ctx,
|
||||
|
|
@ -136,6 +147,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
|||
"mount_path",
|
||||
},
|
||||
},
|
||||
Metadata: md,
|
||||
}, raws...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
@ -183,12 +195,23 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
|||
b.config.MountPartition = "1"
|
||||
}
|
||||
|
||||
if b.config.TemporaryOSDiskName == "" {
|
||||
|
||||
if def, err := interpolate.Render("PackerTemp-{{timestamp}}", &b.config.ctx); err == nil {
|
||||
b.config.TemporaryOSDiskName = def
|
||||
if b.config.TemporaryOSDiskID == "" {
|
||||
if def, err := interpolate.Render(
|
||||
"/subscriptions/{{ vm `subscription_id` }}/resourceGroups/{{ vm `resource_group` }}/providers/Microsoft.Compute/disks/PackerTemp-osdisk-{{timestamp}}",
|
||||
&b.config.ctx); err == nil {
|
||||
b.config.TemporaryOSDiskID = def
|
||||
} else {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("unable to render temporary disk name: %s", err))
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("unable to render temporary disk id: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
if b.config.TemporaryOSDiskSnapshotID == "" {
|
||||
if def, err := interpolate.Render(
|
||||
"/subscriptions/{{ vm `subscription_id` }}/resourceGroups/{{ vm `resource_group` }}/providers/Microsoft.Compute/snapshots/PackerTemp-osdisk-snapshot-{{timestamp}}",
|
||||
&b.config.ctx); err == nil {
|
||||
b.config.TemporaryOSDiskSnapshotID = def
|
||||
} else {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("unable to render temporary snapshot id: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,9 +264,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
|||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("os_disk_storage_account_type: %v", err))
|
||||
}
|
||||
|
||||
if b.config.ImageResourceID == "" {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("image_resource_id is required"))
|
||||
} else {
|
||||
if b.config.ImageResourceID != "" {
|
||||
r, err := azure.ParseResourceID(b.config.ImageResourceID)
|
||||
if err != nil ||
|
||||
!strings.EqualFold(r.Provider, "Microsoft.Compute") ||
|
||||
|
|
@ -253,6 +274,20 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if azcommon.StringsContains(md.Keys, "shared_image_destination") {
|
||||
e, w := b.config.SharedImageGalleryDestination.Validate("shared_image_destination")
|
||||
if len(e) > 0 {
|
||||
errs = packer.MultiErrorAppend(errs, e...)
|
||||
}
|
||||
if len(w) > 0 {
|
||||
warns = append(warns, w...)
|
||||
}
|
||||
}
|
||||
|
||||
if !azcommon.StringsContains(md.Keys, "shared_image_destination") && b.config.ImageResourceID == "" {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("image_resource_id or shared_image_destination is required"))
|
||||
}
|
||||
|
||||
if err := checkHyperVGeneration(b.config.ImageHyperVGeneration); err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("image_hyperv_generation: %v", err))
|
||||
}
|
||||
|
|
@ -336,104 +371,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
state.Put("instance", info)
|
||||
|
||||
// Build the steps
|
||||
var steps []multistep.Step
|
||||
|
||||
if b.config.FromScratch {
|
||||
steps = append(steps,
|
||||
&StepCreateNewDisk{
|
||||
SubscriptionID: info.SubscriptionID,
|
||||
ResourceGroup: info.ResourceGroupName,
|
||||
DiskName: b.config.TemporaryOSDiskName,
|
||||
DiskSizeGB: b.config.OSDiskSizeGB,
|
||||
DiskStorageAccountType: b.config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: b.config.ImageHyperVGeneration,
|
||||
Location: info.Location,
|
||||
})
|
||||
} else {
|
||||
switch b.config.sourceType {
|
||||
case sourcePlatformImage:
|
||||
|
||||
if pi, err := client.ParsePlatformImageURN(b.config.Source); err == nil {
|
||||
if strings.EqualFold(pi.Version, "latest") {
|
||||
|
||||
vmi, err := azcli.VirtualMachineImagesClient().GetLatest(ctx, pi.Publisher, pi.Offer, pi.Sku, info.Location)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error retieving latest version of %q: %v", b.config.Source, err)
|
||||
}
|
||||
pi.Version = to.String(vmi.Name)
|
||||
log.Println("Resolved latest version of source image:", pi.Version)
|
||||
}
|
||||
steps = append(steps,
|
||||
|
||||
&StepCreateNewDisk{
|
||||
SubscriptionID: info.SubscriptionID,
|
||||
ResourceGroup: info.ResourceGroupName,
|
||||
DiskName: b.config.TemporaryOSDiskName,
|
||||
DiskSizeGB: b.config.OSDiskSizeGB,
|
||||
DiskStorageAccountType: b.config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: b.config.ImageHyperVGeneration,
|
||||
Location: info.Location,
|
||||
PlatformImage: pi,
|
||||
|
||||
SkipCleanup: b.config.OSDiskSkipCleanup,
|
||||
})
|
||||
} else {
|
||||
panic("Unknown image source: " + b.config.Source)
|
||||
}
|
||||
case sourceDisk:
|
||||
steps = append(steps,
|
||||
&StepVerifySourceDisk{
|
||||
SourceDiskResourceID: b.config.Source,
|
||||
SubscriptionID: info.SubscriptionID,
|
||||
Location: info.Location,
|
||||
},
|
||||
&StepCreateNewDisk{
|
||||
SubscriptionID: info.SubscriptionID,
|
||||
ResourceGroup: info.ResourceGroupName,
|
||||
DiskName: b.config.TemporaryOSDiskName,
|
||||
DiskSizeGB: b.config.OSDiskSizeGB,
|
||||
DiskStorageAccountType: b.config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: b.config.ImageHyperVGeneration,
|
||||
SourceDiskResourceID: b.config.Source,
|
||||
Location: info.Location,
|
||||
|
||||
SkipCleanup: b.config.OSDiskSkipCleanup,
|
||||
})
|
||||
default:
|
||||
panic(fmt.Errorf("Unknown source type: %+q", b.config.sourceType))
|
||||
}
|
||||
}
|
||||
|
||||
steps = append(steps,
|
||||
&StepAttachDisk{}, // uses os_disk_resource_id and sets 'device' in stateBag
|
||||
&chroot.StepPreMountCommands{
|
||||
Commands: b.config.PreMountCommands,
|
||||
},
|
||||
&StepMountDevice{
|
||||
MountOptions: b.config.MountOptions,
|
||||
MountPartition: b.config.MountPartition,
|
||||
MountPath: b.config.MountPath,
|
||||
},
|
||||
&chroot.StepPostMountCommands{
|
||||
Commands: b.config.PostMountCommands,
|
||||
},
|
||||
&chroot.StepMountExtra{
|
||||
ChrootMounts: b.config.ChrootMounts,
|
||||
},
|
||||
&chroot.StepCopyFiles{
|
||||
Files: b.config.CopyFiles,
|
||||
},
|
||||
&chroot.StepChrootProvision{},
|
||||
&chroot.StepEarlyCleanup{},
|
||||
&StepCreateImage{
|
||||
ImageResourceID: b.config.ImageResourceID,
|
||||
ImageOSState: string(compute.Generalized),
|
||||
OSDiskCacheType: b.config.OSDiskCacheType,
|
||||
OSDiskStorageAccountType: b.config.OSDiskStorageAccountType,
|
||||
Location: info.Location,
|
||||
},
|
||||
)
|
||||
// Build the step array from the config
|
||||
steps := buildsteps(b.config, info)
|
||||
|
||||
// Run!
|
||||
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
|
|
@ -446,12 +385,149 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
// Build the artifact and return it
|
||||
artifact := &azcommon.Artifact{
|
||||
Resources: []string{b.config.ImageResourceID},
|
||||
BuilderIdValue: BuilderId,
|
||||
BuilderIdValue: BuilderID,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
AzureClientSet: azcli,
|
||||
}
|
||||
if b.config.ImageResourceID != "" {
|
||||
artifact.Resources = append(artifact.Resources, b.config.ImageResourceID)
|
||||
}
|
||||
if e, _ := b.config.SharedImageGalleryDestination.Validate(""); len(e) == 0 {
|
||||
artifact.Resources = append(artifact.Resources, b.config.SharedImageGalleryDestination.ResourceID(info.SubscriptionID))
|
||||
}
|
||||
if b.config.SkipCleanup {
|
||||
if d, ok := state.GetOk(stateBagKey_OSDiskResourceID); ok {
|
||||
artifact.Resources = append(artifact.Resources, d.(string))
|
||||
}
|
||||
if d, ok := state.GetOk(stateBagKey_OSDiskSnapshotResourceID); ok {
|
||||
artifact.Resources = append(artifact.Resources, d.(string))
|
||||
}
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
var _ packer.Builder = &Builder{}
|
||||
func buildsteps(config Config, info *client.ComputeInfo) []multistep.Step {
|
||||
// Build the steps
|
||||
var steps []multistep.Step
|
||||
addSteps := func(s ...multistep.Step) { // convenience
|
||||
steps = append(steps, s...)
|
||||
}
|
||||
|
||||
e, _ := config.SharedImageGalleryDestination.Validate("")
|
||||
hasValidSharedImage := len(e) == 0
|
||||
|
||||
if hasValidSharedImage {
|
||||
// validate destination early
|
||||
addSteps(
|
||||
&StepVerifySharedImageDestination{
|
||||
Image: config.SharedImageGalleryDestination,
|
||||
Location: info.Location,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if config.FromScratch {
|
||||
addSteps(&StepCreateNewDisk{
|
||||
ResourceID: config.TemporaryOSDiskID,
|
||||
DiskSizeGB: config.OSDiskSizeGB,
|
||||
DiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: config.ImageHyperVGeneration,
|
||||
Location: info.Location})
|
||||
} else {
|
||||
switch config.sourceType {
|
||||
case sourcePlatformImage:
|
||||
if pi, err := client.ParsePlatformImageURN(config.Source); err == nil {
|
||||
if strings.EqualFold(pi.Version, "latest") {
|
||||
addSteps(
|
||||
&StepResolvePlatformImageVersion{
|
||||
PlatformImage: pi,
|
||||
Location: info.Location,
|
||||
})
|
||||
}
|
||||
addSteps(
|
||||
&StepCreateNewDisk{
|
||||
ResourceID: config.TemporaryOSDiskID,
|
||||
DiskSizeGB: config.OSDiskSizeGB,
|
||||
DiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: config.ImageHyperVGeneration,
|
||||
Location: info.Location,
|
||||
PlatformImage: pi,
|
||||
|
||||
SkipCleanup: config.SkipCleanup,
|
||||
})
|
||||
} else {
|
||||
panic("Couldn't parse platfrom image urn: " + config.Source + " err: " + err.Error())
|
||||
}
|
||||
|
||||
case sourceDisk:
|
||||
addSteps(
|
||||
&StepVerifySourceDisk{
|
||||
SourceDiskResourceID: config.Source,
|
||||
Location: info.Location,
|
||||
},
|
||||
&StepCreateNewDisk{
|
||||
ResourceID: config.TemporaryOSDiskID,
|
||||
DiskSizeGB: config.OSDiskSizeGB,
|
||||
DiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: config.ImageHyperVGeneration,
|
||||
SourceDiskResourceID: config.Source,
|
||||
Location: info.Location,
|
||||
|
||||
SkipCleanup: config.SkipCleanup,
|
||||
})
|
||||
|
||||
default:
|
||||
panic(fmt.Errorf("Unknown source type: %+q", config.sourceType))
|
||||
}
|
||||
}
|
||||
|
||||
addSteps(
|
||||
&StepAttachDisk{}, // uses os_disk_resource_id and sets 'device' in stateBag
|
||||
&chroot.StepPreMountCommands{
|
||||
Commands: config.PreMountCommands,
|
||||
},
|
||||
&StepMountDevice{
|
||||
MountOptions: config.MountOptions,
|
||||
MountPartition: config.MountPartition,
|
||||
MountPath: config.MountPath,
|
||||
},
|
||||
&chroot.StepPostMountCommands{
|
||||
Commands: config.PostMountCommands,
|
||||
},
|
||||
&chroot.StepMountExtra{
|
||||
ChrootMounts: config.ChrootMounts,
|
||||
},
|
||||
&chroot.StepCopyFiles{
|
||||
Files: config.CopyFiles,
|
||||
},
|
||||
&chroot.StepChrootProvision{},
|
||||
&chroot.StepEarlyCleanup{},
|
||||
)
|
||||
|
||||
if config.ImageResourceID != "" {
|
||||
addSteps(&StepCreateImage{
|
||||
ImageResourceID: config.ImageResourceID,
|
||||
ImageOSState: string(compute.Generalized),
|
||||
OSDiskCacheType: config.OSDiskCacheType,
|
||||
OSDiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
Location: info.Location,
|
||||
})
|
||||
}
|
||||
if hasValidSharedImage {
|
||||
addSteps(
|
||||
&StepCreateSnapshot{
|
||||
ResourceID: config.TemporaryOSDiskSnapshotID,
|
||||
Location: info.Location,
|
||||
SkipCleanup: config.SkipCleanup,
|
||||
},
|
||||
&StepCreateSharedImageVersion{
|
||||
Destination: config.SharedImageGalleryDestination,
|
||||
OSDiskCacheType: config.OSDiskCacheType,
|
||||
Location: info.Location,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return steps
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,38 +9,40 @@ 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"`
|
||||
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"`
|
||||
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"`
|
||||
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"`
|
||||
ImageHyperVGeneration *string `mapstructure:"image_hyperv_generation" cty:"image_hyperv_generation"`
|
||||
TemporaryOSDiskID *string `mapstructure:"temporary_os_disk_id" cty:"temporary_os_disk_id"`
|
||||
TemporaryOSDiskSnapshotID *string `mapstructure:"temporary_os_disk_snapshot_id" cty:"temporary_os_disk_snapshot_id"`
|
||||
SkipCleanup *bool `mapstructure:"skip_cleanup" cty:"skip_cleanup"`
|
||||
ImageResourceID *string `mapstructure:"image_resource_id" cty:"image_resource_id"`
|
||||
SharedImageGalleryDestination *FlatSharedImageGalleryDestination `mapstructure:"shared_image_destination" cty:"shared_image_destination"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
|
|
@ -55,38 +57,40 @@ func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec }
|
|||
// 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.AttrSpec{Name: "chroot_mounts", Type: cty.List(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},
|
||||
"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.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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.AttrSpec{Name: "chroot_mounts", Type: cty.List(cty.List(cty.String)), Required: false},
|
||||
"copy_files": &hcldec.AttrSpec{Name: "copy_files", Type: cty.List(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},
|
||||
"image_hyperv_generation": &hcldec.AttrSpec{Name: "image_hyperv_generation", Type: cty.String, Required: false},
|
||||
"temporary_os_disk_id": &hcldec.AttrSpec{Name: "temporary_os_disk_id", Type: cty.String, Required: false},
|
||||
"temporary_os_disk_snapshot_id": &hcldec.AttrSpec{Name: "temporary_os_disk_snapshot_id", Type: cty.String, Required: false},
|
||||
"skip_cleanup": &hcldec.AttrSpec{Name: "skip_cleanup", Type: cty.Bool, Required: false},
|
||||
"image_resource_id": &hcldec.AttrSpec{Name: "image_resource_id", Type: cty.String, Required: false},
|
||||
"shared_image_destination": &hcldec.BlockSpec{TypeName: "shared_image_destination", Nested: hcldec.ObjectSpec((*FlatSharedImageGalleryDestination)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
func TestBuilder_Prepare(t *testing.T) {
|
||||
|
|
@ -17,13 +20,13 @@ func TestBuilder_Prepare(t *testing.T) {
|
|||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "HappyPathFromPlatformImage",
|
||||
name: "platform image to managed disk",
|
||||
config: config{
|
||||
"client_id": "123",
|
||||
"client_secret": "456",
|
||||
"subscription_id": "789",
|
||||
"image_resource_id": "/subscriptions/789/resourceGroups/otherrgname/providers/Microsoft.Compute/images/MyDebianOSImage-{{timestamp}}",
|
||||
"source": "credativ:Debian:9:latest",
|
||||
"image_resource_id": "/subscriptions/789/resourceGroups/otherrgname/providers/Microsoft.Compute/images/MyDebianOSImage-{{timestamp}}",
|
||||
},
|
||||
validate: func(c Config) {
|
||||
if c.OSDiskSizeGB != 0 {
|
||||
|
|
@ -44,27 +47,168 @@ func TestBuilder_Prepare(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "HappyPathFromPlatformImage",
|
||||
name: "disk to managed image, validate temp disk id expansion",
|
||||
config: config{
|
||||
"image_resource_id": "/subscriptions/789/resourceGroups/otherrgname/providers/Microsoft.Compute/images/MyDebianOSImage-{{timestamp}}",
|
||||
"source": "/subscriptions/789/resourceGroups/testrg/providers/Microsoft.Compute/disks/diskname",
|
||||
"image_resource_id": "/subscriptions/789/resourceGroups/otherrgname/providers/Microsoft.Compute/images/MyDebianOSImage-{{timestamp}}",
|
||||
},
|
||||
validate: func(c Config) {
|
||||
prefix := "/subscriptions/testSubscriptionID/resourceGroups/testResourceGroup/providers/Microsoft.Compute/disks/PackerTemp-osdisk-"
|
||||
if !strings.HasPrefix(c.TemporaryOSDiskID, prefix) {
|
||||
t.Errorf("Expected TemporaryOSDiskID to start with %q, but got %q", prefix, c.TemporaryOSDiskID)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "disk to both managed image and shared image",
|
||||
config: config{
|
||||
"source": "/subscriptions/789/resourceGroups/testrg/providers/Microsoft.Compute/disks/diskname",
|
||||
"image_resource_id": "/subscriptions/789/resourceGroups/otherrgname/providers/Microsoft.Compute/images/MyDebianOSImage-{{timestamp}}",
|
||||
"shared_image_destination": config{
|
||||
"resource_group": "rg",
|
||||
"gallery_name": "galleryName",
|
||||
"image_name": "imageName",
|
||||
"image_version": "0.1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "disk to both managed image and shared image with missing property",
|
||||
config: config{
|
||||
"source": "/subscriptions/789/resourceGroups/testrg/providers/Microsoft.Compute/disks/diskname",
|
||||
"image_resource_id": "/subscriptions/789/resourceGroups/otherrgname/providers/Microsoft.Compute/images/MyDebianOSImage-{{timestamp}}",
|
||||
"shared_image_destination": config{
|
||||
"resource_group": "rg",
|
||||
"gallery_name": "galleryName",
|
||||
"image_version": "0.1.0",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "err: no output",
|
||||
config: config{
|
||||
"source": "/subscriptions/789/resourceGroups/testrg/providers/Microsoft.Compute/disks/diskname",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b := &Builder{}
|
||||
withMetadataStub(func() {
|
||||
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)
|
||||
return
|
||||
}
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Builder.Prepare() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if tt.validate != nil {
|
||||
tt.validate(b.config)
|
||||
}
|
||||
if tt.validate != nil {
|
||||
tt.validate(b.config)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_buildsteps(t *testing.T) {
|
||||
info := &client.ComputeInfo{
|
||||
Location: "northpole",
|
||||
Name: "unittestVM",
|
||||
ResourceGroupName: "unittestResourceGroup",
|
||||
SubscriptionID: "96854241-60c7-426d-9a27-3fdeec8957f4",
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
config Config
|
||||
verify func([]multistep.Step, *testing.T)
|
||||
}{
|
||||
{
|
||||
name: "Source FromScrath creates empty disk",
|
||||
config: Config{FromScratch: true},
|
||||
verify: func(steps []multistep.Step, _ *testing.T) {
|
||||
for _, s := range steps {
|
||||
if s, ok := s.(*StepCreateNewDisk); ok {
|
||||
if s.SourceDiskResourceID == "" &&
|
||||
s.PlatformImage == nil {
|
||||
return
|
||||
}
|
||||
t.Errorf("found misconfigured StepCreateNewDisk: %+v", s)
|
||||
}
|
||||
}
|
||||
t.Error("did not find a StepCreateNewDisk")
|
||||
}},
|
||||
{
|
||||
name: "Source Platform image disk creation",
|
||||
config: Config{Source: "publisher:offer:sku:version", sourceType: sourcePlatformImage},
|
||||
verify: func(steps []multistep.Step, _ *testing.T) {
|
||||
for _, s := range steps {
|
||||
if s, ok := s.(*StepCreateNewDisk); ok {
|
||||
if s.SourceDiskResourceID == "" &&
|
||||
s.PlatformImage != nil &&
|
||||
s.PlatformImage.Publisher == "publisher" {
|
||||
return
|
||||
}
|
||||
t.Errorf("found misconfigured StepCreateNewDisk: %+v", s)
|
||||
}
|
||||
}
|
||||
t.Error("did not find a StepCreateNewDisk")
|
||||
}},
|
||||
{
|
||||
name: "Source Platform image with version latest adds StepResolvePlatformImageVersion",
|
||||
config: Config{Source: "publisher:offer:sku:latest", sourceType: sourcePlatformImage},
|
||||
verify: func(steps []multistep.Step, _ *testing.T) {
|
||||
for _, s := range steps {
|
||||
if s, ok := s.(*StepResolvePlatformImageVersion); ok {
|
||||
if s.PlatformImage != nil &&
|
||||
s.Location == info.Location {
|
||||
return
|
||||
}
|
||||
t.Errorf("found misconfigured StepResolvePlatformImageVersion: %+v", s)
|
||||
}
|
||||
}
|
||||
t.Error("did not find a StepResolvePlatformImageVersion")
|
||||
}},
|
||||
{
|
||||
name: "Source Disk adds correct disk creation",
|
||||
config: Config{Source: "diskresourceid", sourceType: sourceDisk},
|
||||
verify: func(steps []multistep.Step, _ *testing.T) {
|
||||
for _, s := range steps {
|
||||
if s, ok := s.(*StepCreateNewDisk); ok {
|
||||
if s.SourceDiskResourceID == "diskresourceid" &&
|
||||
s.PlatformImage == nil {
|
||||
return
|
||||
}
|
||||
t.Errorf("found misconfigured StepCreateNewDisk: %+v", s)
|
||||
}
|
||||
}
|
||||
t.Error("did not find a StepCreateNewDisk")
|
||||
}},
|
||||
{
|
||||
name: "Source disk adds StepVerifySourceDisk",
|
||||
config: Config{Source: "diskresourceid", sourceType: sourceDisk},
|
||||
verify: func(steps []multistep.Step, _ *testing.T) {
|
||||
for _, s := range steps {
|
||||
if s, ok := s.(*StepVerifySourceDisk); ok {
|
||||
if s.SourceDiskResourceID == "diskresourceid" &&
|
||||
s.Location == info.Location {
|
||||
return
|
||||
}
|
||||
t.Errorf("found misconfigured StepVerifySourceDisk: %+v", s)
|
||||
}
|
||||
}
|
||||
t.Error("did not find a StepVerifySourceDisk")
|
||||
}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
withMetadataStub(func() { // ensure that values are taken from info, instead of retrieved again
|
||||
got := buildsteps(tt.config, info)
|
||||
tt.verify(got, t)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
builder/azure/chroot/const.go
Normal file
6
builder/azure/chroot/const.go
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package chroot
|
||||
|
||||
const (
|
||||
stateBagKey_OSDiskResourceID = "os_disk_resource_id"
|
||||
stateBagKey_OSDiskSnapshotResourceID = "os_disk_snapshot_resource_id"
|
||||
)
|
||||
|
|
@ -13,7 +13,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-03-01/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
|
|||
18
builder/azure/chroot/metadatastub_test.go
Normal file
18
builder/azure/chroot/metadatastub_test.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package chroot
|
||||
|
||||
import "github.com/hashicorp/packer/builder/azure/common/client"
|
||||
|
||||
func withMetadataStub(f func()) {
|
||||
mdc := client.DefaultMetadataClient
|
||||
defer func() { client.DefaultMetadataClient = mdc }()
|
||||
client.DefaultMetadataClient = client.MetadataClientStub{
|
||||
ComputeInfo: client.ComputeInfo{
|
||||
SubscriptionID: "testSubscriptionID",
|
||||
ResourceGroupName: "testResourceGroup",
|
||||
Name: "testVM",
|
||||
Location: "testLocation",
|
||||
},
|
||||
}
|
||||
|
||||
f()
|
||||
}
|
||||
19
builder/azure/chroot/packerui_test.go
Normal file
19
builder/azure/chroot/packerui_test.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// testUI returns a test ui plus a function to retrieve the errors written to the ui
|
||||
func testUI() (packer.Ui, func() string) {
|
||||
errorBuffer := &strings.Builder{}
|
||||
ui := &packer.BasicUi{
|
||||
Reader: strings.NewReader(""),
|
||||
Writer: ioutil.Discard,
|
||||
ErrorWriter: errorBuffer,
|
||||
}
|
||||
return ui, errorBuffer.String
|
||||
}
|
||||
65
builder/azure/chroot/shared_image_gallery_destination.go
Normal file
65
builder/azure/chroot/shared_image_gallery_destination.go
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type SharedImageGalleryDestination,TargetRegion
|
||||
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// SharedImageGalleryDestination models an image version in a Shared
|
||||
// Image Gallery that can be used as a destination.
|
||||
type SharedImageGalleryDestination struct {
|
||||
ResourceGroup string `mapstructure:"resource_group" required:"true"`
|
||||
GalleryName string `mapstructure:"gallery_name" required:"true"`
|
||||
ImageName string `mapstructure:"image_name" required:"true"`
|
||||
ImageVersion string `mapstructure:"image_version" required:"true"`
|
||||
|
||||
TargetRegions []TargetRegion `mapstructure:"target_regions"`
|
||||
ExcludeFromLatest bool `mapstructure:"exlude_from_latest"`
|
||||
}
|
||||
|
||||
// TargetRegion describes a region where the shared image should be replicated
|
||||
type TargetRegion struct {
|
||||
// Name of the Azure region
|
||||
Name string `mapstructure:"name" required:"true"`
|
||||
// Number of replicas in this region. Default: 1
|
||||
ReplicaCount int32 `mapstructure:"replicas"`
|
||||
// Storage account type: Standard_LRS or Standard_ZRS. Default: Standard_ZRS
|
||||
StorageAccountType string `mapstructure:"storage_account_type"`
|
||||
}
|
||||
|
||||
// ResourceID returns the resource ID string
|
||||
func (sigd SharedImageGalleryDestination) ResourceID(subscriptionID string) string {
|
||||
return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/galleries/%s/images/%s/versions/%s",
|
||||
subscriptionID,
|
||||
sigd.ResourceGroup,
|
||||
sigd.GalleryName,
|
||||
sigd.ImageName,
|
||||
sigd.ImageVersion)
|
||||
}
|
||||
|
||||
// Validate validates that the values in the shared image are valid (without checking them on the network)
|
||||
func (sigd *SharedImageGalleryDestination) Validate(prefix string) (errs []error, warns []string) {
|
||||
if sigd.ResourceGroup == "" {
|
||||
errs = append(errs, fmt.Errorf("%s.resource_group is required", prefix))
|
||||
}
|
||||
if sigd.GalleryName == "" {
|
||||
errs = append(errs, fmt.Errorf("%s.gallery_name is required", prefix))
|
||||
}
|
||||
if sigd.ImageName == "" {
|
||||
errs = append(errs, fmt.Errorf("%s.image_name is required", prefix))
|
||||
}
|
||||
if match, err := regexp.MatchString("^[0-9]+\\.[0-9]+\\.[0-9]+$", sigd.ImageVersion); !match {
|
||||
if err != nil {
|
||||
warns = append(warns, fmt.Sprintf("Error matching pattern for %s.image_version: %s (this is probably a bug)", prefix, err))
|
||||
}
|
||||
errs = append(errs, fmt.Errorf("%s.image_version should match '^[0-9]+\\.[0-9]+\\.[0-9]+$'", prefix))
|
||||
}
|
||||
if len(sigd.TargetRegions) == 0 {
|
||||
warns = append(warns,
|
||||
fmt.Sprintf("%s.target_regions is empty; image will only be available in the region of the gallery", prefix))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type SharedImageGalleryDestination,TargetRegion"; DO NOT EDIT.
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatSharedImageGalleryDestination is an auto-generated flat version of SharedImageGalleryDestination.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatSharedImageGalleryDestination struct {
|
||||
ResourceGroup *string `mapstructure:"resource_group" required:"true" cty:"resource_group"`
|
||||
GalleryName *string `mapstructure:"gallery_name" required:"true" cty:"gallery_name"`
|
||||
ImageName *string `mapstructure:"image_name" required:"true" cty:"image_name"`
|
||||
ImageVersion *string `mapstructure:"image_version" required:"true" cty:"image_version"`
|
||||
TargetRegions []FlatTargetRegion `mapstructure:"target_regions" cty:"target_regions"`
|
||||
ExcludeFromLatest *bool `mapstructure:"exlude_from_latest" cty:"exlude_from_latest"`
|
||||
}
|
||||
|
||||
// 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{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(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},
|
||||
"gallery_name": &hcldec.AttrSpec{Name: "gallery_name", 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},
|
||||
"target_regions": &hcldec.BlockListSpec{TypeName: "target_regions", Nested: hcldec.ObjectSpec((*FlatTargetRegion)(nil).HCL2Spec())},
|
||||
"exlude_from_latest": &hcldec.AttrSpec{Name: "exlude_from_latest", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatTargetRegion is an auto-generated flat version of TargetRegion.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatTargetRegion struct {
|
||||
Name *string `mapstructure:"name" required:"true" cty:"name"`
|
||||
ReplicaCount *int32 `mapstructure:"replicas" cty:"replicas"`
|
||||
StorageAccountType *string `mapstructure:"storage_account_type" cty:"storage_account_type"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatTargetRegion.
|
||||
// FlatTargetRegion is an auto-generated flat version of TargetRegion.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*TargetRegion) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatTargetRegion)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a TargetRegion.
|
||||
// This spec is used by HCL to read the fields of TargetRegion.
|
||||
// The decoded values from this spec will then be applied to a FlatTargetRegion.
|
||||
func (*FlatTargetRegion) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"name": &hcldec.AttrSpec{Name: "name", Type: cty.String, Required: false},
|
||||
"replicas": &hcldec.AttrSpec{Name: "replicas", Type: cty.Number, Required: false},
|
||||
"storage_account_type": &hcldec.AttrSpec{Name: "storage_account_type", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
133
builder/azure/chroot/shared_image_gallery_destination_test.go
Normal file
133
builder/azure/chroot/shared_image_gallery_destination_test.go
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSharedImageGalleryDestination_ResourceID(t *testing.T) {
|
||||
sigd := SharedImageGalleryDestination{
|
||||
ResourceGroup: "ResourceGroup",
|
||||
GalleryName: "GalleryName",
|
||||
ImageName: "ImageName",
|
||||
ImageVersion: "ImageVersion",
|
||||
}
|
||||
want := "/subscriptions/SubscriptionID/resourceGroups/ResourceGroup/providers/Microsoft.Compute/galleries/GalleryName/images/ImageName/versions/ImageVersion"
|
||||
if got := sigd.ResourceID("SubscriptionID"); !strings.EqualFold(got, want) {
|
||||
t.Errorf("SharedImageGalleryDestination.ResourceID() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSharedImageGalleryDestination_Validate(t *testing.T) {
|
||||
type fields struct {
|
||||
ResourceGroup string
|
||||
GalleryName string
|
||||
ImageName string
|
||||
ImageVersion string
|
||||
TargetRegions []TargetRegion
|
||||
ExcludeFromLatest bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErrs []string
|
||||
wantWarns []string
|
||||
}{
|
||||
{
|
||||
name: "complete",
|
||||
fields: fields{
|
||||
ResourceGroup: "ResourceGroup",
|
||||
GalleryName: "GalleryName",
|
||||
ImageName: "ImageName",
|
||||
ImageVersion: "0.1.2",
|
||||
TargetRegions: []TargetRegion{
|
||||
TargetRegion{
|
||||
Name: "region1",
|
||||
ReplicaCount: 5,
|
||||
StorageAccountType: "Standard_ZRS",
|
||||
},
|
||||
TargetRegion{
|
||||
Name: "region2",
|
||||
ReplicaCount: 3,
|
||||
StorageAccountType: "Standard_LRS",
|
||||
},
|
||||
},
|
||||
ExcludeFromLatest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "warn if target regions not specified",
|
||||
fields: fields{
|
||||
ResourceGroup: "ResourceGroup",
|
||||
GalleryName: "GalleryName",
|
||||
ImageName: "ImageName",
|
||||
ImageVersion: "0.1.2",
|
||||
},
|
||||
wantWarns: []string{"sigdest.target_regions is empty; image will only be available in the region of the gallery"},
|
||||
},
|
||||
{
|
||||
name: "version format",
|
||||
wantErrs: []string{
|
||||
"sigdest.image_version should match '^[0-9]+\\.[0-9]+\\.[0-9]+$'",
|
||||
},
|
||||
fields: fields{
|
||||
ResourceGroup: "ResourceGroup",
|
||||
GalleryName: "GalleryName",
|
||||
ImageName: "ImageName",
|
||||
ImageVersion: "0.1.2alpha",
|
||||
TargetRegions: []TargetRegion{
|
||||
TargetRegion{
|
||||
Name: "region1",
|
||||
ReplicaCount: 5,
|
||||
StorageAccountType: "Standard_ZRS",
|
||||
},
|
||||
TargetRegion{
|
||||
Name: "region2",
|
||||
ReplicaCount: 3,
|
||||
StorageAccountType: "Standard_LRS",
|
||||
},
|
||||
},
|
||||
ExcludeFromLatest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "required fields",
|
||||
wantErrs: []string{
|
||||
"sigdest.resource_group is required",
|
||||
"sigdest.gallery_name is required",
|
||||
"sigdest.image_name is required",
|
||||
"sigdest.image_version should match '^[0-9]+\\.[0-9]+\\.[0-9]+$'",
|
||||
},
|
||||
wantWarns: []string{"sigdest.target_regions is empty; image will only be available in the region of the gallery"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
sigd := &SharedImageGalleryDestination{
|
||||
ResourceGroup: tt.fields.ResourceGroup,
|
||||
GalleryName: tt.fields.GalleryName,
|
||||
ImageName: tt.fields.ImageName,
|
||||
ImageVersion: tt.fields.ImageVersion,
|
||||
TargetRegions: tt.fields.TargetRegions,
|
||||
ExcludeFromLatest: tt.fields.ExcludeFromLatest,
|
||||
}
|
||||
gotErrs, gotWarns := sigd.Validate("sigdest")
|
||||
|
||||
var gotStrErrs []string
|
||||
if gotErrs != nil {
|
||||
gotStrErrs = make([]string, len(gotErrs))
|
||||
for i, e := range gotErrs {
|
||||
gotStrErrs[i] = e.Error()
|
||||
}
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gotStrErrs, tt.wantErrs) {
|
||||
t.Errorf("SharedImageGalleryDestination.Validate() gotErrs = %q, want %q", gotStrErrs, tt.wantErrs)
|
||||
}
|
||||
if !reflect.DeepEqual(gotWarns, tt.wantWarns) {
|
||||
t.Errorf("SharedImageGalleryDestination.Validate() gotWarns = %q, want %q", gotWarns, tt.wantWarns)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ type StepAttachDisk struct {
|
|||
func (s *StepAttachDisk) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
diskResourceID := state.Get("os_disk_resource_id").(string)
|
||||
diskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
|
||||
ui.Say(fmt.Sprintf("Attaching disk '%s'", diskResourceID))
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ func (s *StepAttachDisk) CleanupFunc(state multistep.StateBag) error {
|
|||
if s.attached {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
diskResourceID := state.Get("os_disk_resource_id").(string)
|
||||
diskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
|
||||
ui.Say(fmt.Sprintf("Detaching disk '%s'", diskResourceID))
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
|
|
@ -78,7 +78,7 @@ func TestStepAttachDisk_Run(t *testing.T) {
|
|||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{})
|
||||
state.Put("ui", ui)
|
||||
state.Put("os_disk_resource_id", "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/disk1")
|
||||
state.Put(stateBagKey_OSDiskResourceID, "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/disk1")
|
||||
|
||||
got := s.Run(context.TODO(), state)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-03-01/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
|
|
@ -28,7 +28,7 @@ type StepCreateImage struct {
|
|||
func (s *StepCreateImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
diskResourceID := state.Get("os_disk_resource_id").(string)
|
||||
diskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating image %s\n using %s for os disk.",
|
||||
s.ImageResourceID,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-03-01/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-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"
|
||||
|
|
@ -15,10 +18,12 @@ import (
|
|||
var _ multistep.Step = &StepCreateNewDisk{}
|
||||
|
||||
type StepCreateNewDisk struct {
|
||||
SubscriptionID, ResourceGroup, DiskName string
|
||||
DiskSizeGB int32 // optional, ignored if 0
|
||||
DiskStorageAccountType string // from compute.DiskStorageAccountTypes
|
||||
HyperVGeneration string
|
||||
ResourceID string // Disk ID
|
||||
subscriptionID, resourceGroup, diskName string // split out resource id
|
||||
|
||||
DiskSizeGB int32 // optional, ignored if 0
|
||||
DiskStorageAccountType string // from compute.DiskStorageAccountTypes
|
||||
HyperVGeneration string
|
||||
|
||||
Location string
|
||||
PlatformImage *client.PlatformImage
|
||||
|
|
@ -28,16 +33,37 @@ type StepCreateNewDisk struct {
|
|||
SkipCleanup bool
|
||||
}
|
||||
|
||||
func (s StepCreateNewDisk) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
func parseDiskResourceID(resourceID string) (subscriptionID, resourceGroup, diskName string, err error) {
|
||||
r, err := azure.ParseResourceID(resourceID)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
if !strings.EqualFold(r.Provider, "Microsoft.Compute") ||
|
||||
!strings.EqualFold(r.ResourceType, "disks") {
|
||||
return "", "", "", fmt.Errorf("Resource %q is not of type Microsoft.Compute/disks", resourceID)
|
||||
}
|
||||
|
||||
return r.SubscriptionID, r.ResourceGroup, r.ResourceName, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateNewDisk) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
diskResourceID := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/disks/%s",
|
||||
s.SubscriptionID,
|
||||
s.ResourceGroup,
|
||||
s.DiskName)
|
||||
state.Put("os_disk_resource_id", diskResourceID)
|
||||
ui.Say(fmt.Sprintf("Creating disk '%s'", diskResourceID))
|
||||
state.Put(stateBagKey_OSDiskResourceID, s.ResourceID)
|
||||
ui.Say(fmt.Sprintf("Creating disk '%s'", s.ResourceID))
|
||||
|
||||
var err error
|
||||
s.subscriptionID, s.resourceGroup, s.diskName, err = parseDiskResourceID(s.ResourceID)
|
||||
if err != nil {
|
||||
log.Printf("StepCreateNewDisk.Run: error: %+v", err)
|
||||
err := fmt.Errorf(
|
||||
"error parsing resource id '%s': %v", s.ResourceID, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
disk := compute.Disk{
|
||||
Location: to.StringPtr(s.Location),
|
||||
|
|
@ -67,18 +93,20 @@ func (s StepCreateNewDisk) Run(ctx context.Context, state multistep.StateBag) mu
|
|||
disk.CreationData.ImageReference = &compute.ImageDiskReference{
|
||||
ID: to.StringPtr(fmt.Sprintf(
|
||||
"/subscriptions/%s/providers/Microsoft.Compute/locations/%s/publishers/%s/artifacttypes/vmimage/offers/%s/skus/%s/versions/%s",
|
||||
s.SubscriptionID, s.Location, s.PlatformImage.Publisher, s.PlatformImage.Offer, s.PlatformImage.Sku, s.PlatformImage.Version)),
|
||||
s.subscriptionID, s.Location, s.PlatformImage.Publisher, s.PlatformImage.Offer, s.PlatformImage.Sku, s.PlatformImage.Version)),
|
||||
}
|
||||
}
|
||||
|
||||
f, err := azcli.DisksClient().CreateOrUpdate(ctx, s.ResourceGroup, s.DiskName, disk)
|
||||
f, err := azcli.DisksClient().CreateOrUpdate(ctx, s.resourceGroup, s.diskName, disk)
|
||||
if err == nil {
|
||||
err = f.WaitForCompletionRef(ctx, azcli.PollClient())
|
||||
cli := azcli.PollClient() // quick polling for quick operations
|
||||
cli.PollingDelay = time.Second
|
||||
err = f.WaitForCompletionRef(ctx, cli)
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateNewDisk.Run: error: %+v", err)
|
||||
err := fmt.Errorf(
|
||||
"error creating new disk '%s': %v", diskResourceID, err)
|
||||
"error creating new disk '%s': %v", s.ResourceID, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
|
@ -87,27 +115,26 @@ func (s StepCreateNewDisk) Run(ctx context.Context, state multistep.StateBag) mu
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s StepCreateNewDisk) Cleanup(state multistep.StateBag) {
|
||||
func (s *StepCreateNewDisk) Cleanup(state multistep.StateBag) {
|
||||
if !s.SkipCleanup {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
diskResourceID := state.Get("os_disk_resource_id").(string)
|
||||
|
||||
ui.Say(fmt.Sprintf("Waiting for disk %q detach to complete", diskResourceID))
|
||||
err := NewDiskAttacher(azcli).WaitForDetach(context.Background(), diskResourceID)
|
||||
ui.Say(fmt.Sprintf("Waiting for disk %q detach to complete", s.ResourceID))
|
||||
err := NewDiskAttacher(azcli).WaitForDetach(context.Background(), s.ResourceID)
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("error detaching disk %q: %s", diskResourceID, err))
|
||||
ui.Error(fmt.Sprintf("error detaching disk %q: %s", s.ResourceID, err))
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Deleting disk %q", diskResourceID))
|
||||
ui.Say(fmt.Sprintf("Deleting disk %q", s.ResourceID))
|
||||
|
||||
f, err := azcli.DisksClient().Delete(context.TODO(), s.ResourceGroup, s.DiskName)
|
||||
f, err := azcli.DisksClient().Delete(context.TODO(), s.resourceGroup, s.diskName)
|
||||
if err == nil {
|
||||
err = f.WaitForCompletionRef(context.TODO(), azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateNewDisk.Cleanup: error: %+v", err)
|
||||
ui.Error(fmt.Sprintf("error deleting new disk '%s': %v.", diskResourceID, err))
|
||||
ui.Error(fmt.Sprintf("error deleting disk '%s': %v.", s.ResourceID, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,18 +8,17 @@ import (
|
|||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
func TestStepCreateNewDisk_Run(t *testing.T) {
|
||||
type fields struct {
|
||||
SubscriptionID string
|
||||
ResourceGroup string
|
||||
DiskName string
|
||||
ResourceID string
|
||||
DiskSizeGB int32
|
||||
DiskStorageAccountType string
|
||||
HyperVGeneration string
|
||||
|
|
@ -35,11 +34,9 @@ func TestStepCreateNewDisk_Run(t *testing.T) {
|
|||
want multistep.StepAction
|
||||
}{
|
||||
{
|
||||
name: "HappyPathDiskSource",
|
||||
name: "from disk",
|
||||
fields: fields{
|
||||
SubscriptionID: "SubscriptionID",
|
||||
ResourceGroup: "ResourceGroupName",
|
||||
DiskName: "TemporaryOSDiskName",
|
||||
ResourceID: "/subscriptions/SubscriptionID/resourcegroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName",
|
||||
DiskSizeGB: 42,
|
||||
DiskStorageAccountType: string(compute.PremiumLRS),
|
||||
HyperVGeneration: string(compute.V1),
|
||||
|
|
@ -66,11 +63,9 @@ func TestStepCreateNewDisk_Run(t *testing.T) {
|
|||
want: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "HappyPathDiskSource",
|
||||
name: "from image",
|
||||
fields: fields{
|
||||
SubscriptionID: "SubscriptionID",
|
||||
ResourceGroup: "ResourceGroupName",
|
||||
DiskName: "TemporaryOSDiskName",
|
||||
ResourceID: "/subscriptions/SubscriptionID/resourcegroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName",
|
||||
DiskStorageAccountType: string(compute.StandardLRS),
|
||||
HyperVGeneration: string(compute.V1),
|
||||
Location: "westus",
|
||||
|
|
@ -105,9 +100,7 @@ func TestStepCreateNewDisk_Run(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := StepCreateNewDisk{
|
||||
SubscriptionID: tt.fields.SubscriptionID,
|
||||
ResourceGroup: tt.fields.ResourceGroup,
|
||||
DiskName: tt.fields.DiskName,
|
||||
ResourceID: tt.fields.ResourceID,
|
||||
DiskSizeGB: tt.fields.DiskSizeGB,
|
||||
DiskStorageAccountType: tt.fields.DiskStorageAccountType,
|
||||
HyperVGeneration: tt.fields.HyperVGeneration,
|
||||
|
|
|
|||
81
builder/azure/chroot/step_create_shared_image_version.go
Normal file
81
builder/azure/chroot/step_create_shared_image_version.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"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"
|
||||
)
|
||||
|
||||
type StepCreateSharedImageVersion struct {
|
||||
Destination SharedImageGalleryDestination
|
||||
OSDiskCacheType string
|
||||
Location string
|
||||
}
|
||||
|
||||
func (s *StepCreateSharedImageVersion) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
osDiskSnapshotResourceID := state.Get(stateBagKey_OSDiskSnapshotResourceID).(string)
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating image version %s\n using %s for os disk.",
|
||||
s.Destination.ResourceID(azcli.SubscriptionID()),
|
||||
osDiskSnapshotResourceID))
|
||||
|
||||
var targetRegions []compute.TargetRegion
|
||||
// transform target regions to API objects
|
||||
for _, tr := range s.Destination.TargetRegions {
|
||||
apiObject := compute.TargetRegion{
|
||||
Name: to.StringPtr(tr.Name),
|
||||
RegionalReplicaCount: to.Int32Ptr(tr.ReplicaCount),
|
||||
StorageAccountType: compute.StorageAccountType(tr.StorageAccountType),
|
||||
}
|
||||
targetRegions = append(targetRegions, apiObject)
|
||||
}
|
||||
|
||||
imageVersion := compute.GalleryImageVersion{
|
||||
Location: to.StringPtr(s.Location),
|
||||
GalleryImageVersionProperties: &compute.GalleryImageVersionProperties{
|
||||
StorageProfile: &compute.GalleryImageVersionStorageProfile{
|
||||
OsDiskImage: &compute.GalleryOSDiskImage{
|
||||
Source: &compute.GalleryArtifactVersionSource{ID: &osDiskSnapshotResourceID},
|
||||
HostCaching: compute.HostCaching(s.OSDiskCacheType),
|
||||
},
|
||||
},
|
||||
PublishingProfile: &compute.GalleryImageVersionPublishingProfile{
|
||||
TargetRegions: &targetRegions,
|
||||
ExcludeFromLatest: to.BoolPtr(s.Destination.ExcludeFromLatest),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
f, err := azcli.GalleryImageVersionsClient().CreateOrUpdate(
|
||||
ctx,
|
||||
s.Destination.ResourceGroup,
|
||||
s.Destination.GalleryName,
|
||||
s.Destination.ImageName,
|
||||
s.Destination.ImageVersion,
|
||||
imageVersion)
|
||||
if err == nil {
|
||||
log.Println("Shared image version creation in process...")
|
||||
err = f.WaitForCompletionRef(ctx, azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateSharedImageVersion.Run: error: %+v", err)
|
||||
err := fmt.Errorf(
|
||||
"error creating shared image version '%s': %v", s.Destination.ResourceID(azcli.SubscriptionID()), err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
log.Printf("Image creation complete: %s", f.Status())
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (*StepCreateSharedImageVersion) Cleanup(multistep.StateBag) {}
|
||||
110
builder/azure/chroot/step_create_shared_image_version_test.go
Normal file
110
builder/azure/chroot/step_create_shared_image_version_test.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
func TestStepCreateSharedImageVersion_Run(t *testing.T) {
|
||||
type fields struct {
|
||||
Destination SharedImageGalleryDestination
|
||||
OSDiskCacheType string
|
||||
Location string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want multistep.StepAction
|
||||
expectedPutBody string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
fields: fields{
|
||||
Destination: SharedImageGalleryDestination{
|
||||
ResourceGroup: "ResourceGroup",
|
||||
GalleryName: "GalleryName",
|
||||
ImageName: "ImageName",
|
||||
ImageVersion: "0.1.2",
|
||||
TargetRegions: []TargetRegion{
|
||||
TargetRegion{
|
||||
Name: "region1",
|
||||
ReplicaCount: 5,
|
||||
StorageAccountType: "Standard_ZRS",
|
||||
},
|
||||
},
|
||||
ExcludeFromLatest: true,
|
||||
},
|
||||
Location: "region2",
|
||||
},
|
||||
expectedPutBody: `{
|
||||
"location": "region2",
|
||||
"properties": {
|
||||
"publishingProfile": {
|
||||
"targetRegions": [
|
||||
{
|
||||
"name": "region1",
|
||||
"regionalReplicaCount": 5,
|
||||
"storageAccountType": "Standard_ZRS"
|
||||
}
|
||||
],
|
||||
"excludeFromLatest": true
|
||||
},
|
||||
"storageProfile": {
|
||||
"osDiskImage": {
|
||||
"source": {
|
||||
"id": "osdisksnapshotresourceid"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
expectedPutBody := regexp.MustCompile(`[\s\n]`).ReplaceAllString(tt.expectedPutBody, "")
|
||||
|
||||
m := compute.NewGalleryImageVersionsClient("subscriptionId")
|
||||
m.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if r.Method != "PUT" {
|
||||
t.Fatal("Expected only a PUT call")
|
||||
}
|
||||
b, _ := ioutil.ReadAll(r.Body)
|
||||
if string(b) != expectedPutBody {
|
||||
t.Errorf("expected body to be %v, but got %v", expectedPutBody, string(b))
|
||||
}
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
})
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
GalleryImageVersionsClientMock: m,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
state.Put(stateBagKey_OSDiskSnapshotResourceID, "osdisksnapshotresourceid")
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StepCreateSharedImageVersion{
|
||||
Destination: tt.fields.Destination,
|
||||
OSDiskCacheType: tt.fields.OSDiskCacheType,
|
||||
Location: tt.fields.Location,
|
||||
}
|
||||
if got := s.Run(context.TODO(), state); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("StepCreateSharedImageVersion.Run() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
123
builder/azure/chroot/step_create_snapshot.go
Normal file
123
builder/azure/chroot/step_create_snapshot.go
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
)
|
||||
|
||||
var _ multistep.Step = &StepCreateSnapshot{}
|
||||
|
||||
type StepCreateSnapshot struct {
|
||||
ResourceID string
|
||||
Location string
|
||||
|
||||
SkipCleanup bool
|
||||
|
||||
subscriptionID, resourceGroup, snapshotName string
|
||||
}
|
||||
|
||||
func parseSnapshotResourceID(resourceID string) (subscriptionID, resourceGroup, snapshotName string, err error) {
|
||||
r, err := azure.ParseResourceID(resourceID)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
if !strings.EqualFold(r.Provider, "Microsoft.Compute") ||
|
||||
!strings.EqualFold(r.ResourceType, "snapshots") {
|
||||
return "", "", "", fmt.Errorf("Resource %q is not of type Microsoft.Compute/snapshots", resourceID)
|
||||
}
|
||||
|
||||
return r.SubscriptionID, r.ResourceGroup, r.ResourceName, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
osDiskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
|
||||
state.Put(stateBagKey_OSDiskSnapshotResourceID, s.ResourceID)
|
||||
ui.Say(fmt.Sprintf("Creating snapshot '%s'", s.ResourceID))
|
||||
|
||||
var err error
|
||||
s.subscriptionID, s.resourceGroup, s.snapshotName, err = parseSnapshotResourceID(s.ResourceID)
|
||||
if err != nil {
|
||||
log.Printf("StepCreateSnapshot.Run: error: %+v", err)
|
||||
err := fmt.Errorf(
|
||||
"error parsing resource id '%s': %v", s.ResourceID, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
snapshot := compute.Snapshot{
|
||||
Location: to.StringPtr(s.Location),
|
||||
SnapshotProperties: &compute.SnapshotProperties{
|
||||
CreationData: &compute.CreationData{
|
||||
CreateOption: compute.Copy,
|
||||
SourceResourceID: to.StringPtr(osDiskResourceID),
|
||||
},
|
||||
Incremental: to.BoolPtr(false),
|
||||
},
|
||||
}
|
||||
|
||||
f, err := azcli.SnapshotsClient().CreateOrUpdate(ctx, s.resourceGroup, s.snapshotName, snapshot)
|
||||
if err == nil {
|
||||
cli := azcli.PollClient() // quick polling for quick operations
|
||||
cli.PollingDelay = time.Second
|
||||
err = f.WaitForCompletionRef(ctx, cli)
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateSnapshot.Run: error: %+v", err)
|
||||
err := fmt.Errorf(
|
||||
"error creating snapshot '%s': %v", s.ResourceID, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCreateSnapshot) Cleanup(state multistep.StateBag) {
|
||||
if !s.SkipCleanup {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say(fmt.Sprintf("Removing any active SAS for snapshot %q", s.ResourceID))
|
||||
{
|
||||
f, err := azcli.SnapshotsClient().RevokeAccess(context.TODO(), s.resourceGroup, s.snapshotName)
|
||||
if err == nil {
|
||||
log.Printf("StepCreateSnapshot.Cleanup: removing SAS...")
|
||||
err = f.WaitForCompletionRef(context.TODO(), azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateSnapshot.Cleanup: error: %+v", err)
|
||||
ui.Error(fmt.Sprintf("error deleting snapshot '%s': %v.", s.ResourceID, err))
|
||||
}
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Deleting snapshot %q", s.ResourceID))
|
||||
{
|
||||
f, err := azcli.SnapshotsClient().Delete(context.TODO(), s.resourceGroup, s.snapshotName)
|
||||
if err == nil {
|
||||
log.Printf("StepCreateSnapshot.Cleanup: deleting snapshot...")
|
||||
err = f.WaitForCompletionRef(context.TODO(), azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateSnapshot.Cleanup: error: %+v", err)
|
||||
ui.Error(fmt.Sprintf("error deleting snapshot '%s': %v.", s.ResourceID, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
215
builder/azure/chroot/step_create_snapshot_test.go
Normal file
215
builder/azure/chroot/step_create_snapshot_test.go
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func Test_parseSnapshotResourceID(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
resourceID string
|
||||
wantSubscriptionID string
|
||||
wantResourceGroup string
|
||||
wantSnapshotName string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
resourceID: "/subscriptions/1234/resourceGroups/rg/providers/microsoft.compute/snapshots/disksnapshot1",
|
||||
wantErr: false,
|
||||
wantSubscriptionID: "1234",
|
||||
wantResourceGroup: "rg",
|
||||
wantSnapshotName: "disksnapshot1",
|
||||
},
|
||||
{
|
||||
name: "error: nonsense",
|
||||
resourceID: "nonsense",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error: other resource type",
|
||||
resourceID: "/subscriptions/1234/resourceGroups/rg/providers/microsoft.compute/disks/disksnapshot1",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error: no name",
|
||||
resourceID: "/subscriptions/1234/resourceGroups/rg/providers/microsoft.compute/snapshots",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotSubscriptionID, gotResourceGroup, gotSnapshotName, err := parseSnapshotResourceID(tt.resourceID)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("parseSnapshotResourceID() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if gotSubscriptionID != tt.wantSubscriptionID {
|
||||
t.Errorf("parseSnapshotResourceID() gotSubscriptionID = %v, want %v", gotSubscriptionID, tt.wantSubscriptionID)
|
||||
}
|
||||
if gotResourceGroup != tt.wantResourceGroup {
|
||||
t.Errorf("parseSnapshotResourceID() gotResourceGroup = %v, want %v", gotResourceGroup, tt.wantResourceGroup)
|
||||
}
|
||||
if gotSnapshotName != tt.wantSnapshotName {
|
||||
t.Errorf("parseSnapshotResourceID() gotSnapshotName = %v, want %v", gotSnapshotName, tt.wantSnapshotName)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateSnapshot_Run(t *testing.T) {
|
||||
type fields struct {
|
||||
ResourceID string
|
||||
Location string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want multistep.StepAction
|
||||
wantSnapshotID string
|
||||
expectedPutBody string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
fields: fields{
|
||||
ResourceID: "/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/snap1",
|
||||
Location: "region1",
|
||||
},
|
||||
expectedPutBody: `{
|
||||
"location": "region1",
|
||||
"properties": {
|
||||
"creationData": {
|
||||
"createOption": "Copy",
|
||||
"sourceResourceId": "osdiskresourceid"
|
||||
},
|
||||
"incremental": false
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: "invalid ResourceID",
|
||||
fields: fields{
|
||||
ResourceID: "notaresourceid",
|
||||
Location: "region1",
|
||||
},
|
||||
want: multistep.ActionHalt,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
expectedPutBody := regexp.MustCompile(`[\s\n]`).ReplaceAllString(tt.expectedPutBody, "")
|
||||
|
||||
m := compute.NewSnapshotsClient("subscriptionId")
|
||||
m.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if r.Method != "PUT" {
|
||||
t.Fatal("Expected only a PUT call")
|
||||
}
|
||||
b, _ := ioutil.ReadAll(r.Body)
|
||||
if string(b) != expectedPutBody {
|
||||
t.Errorf("expected body to be %v, but got %v", expectedPutBody, string(b))
|
||||
}
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
})
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
SnapshotsClientMock: m,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
state.Put(stateBagKey_OSDiskResourceID, "osdiskresourceid")
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StepCreateSnapshot{
|
||||
ResourceID: tt.fields.ResourceID,
|
||||
Location: tt.fields.Location,
|
||||
}
|
||||
if got := s.Run(context.TODO(), state); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("StepCreateSnapshot.Run() = %v, want %v", got, tt.want)
|
||||
}
|
||||
|
||||
if tt.wantSnapshotID != "" {
|
||||
got := state.Get(stateBagKey_OSDiskSnapshotResourceID).(string)
|
||||
if !strings.EqualFold(got, tt.wantSnapshotID) {
|
||||
t.Errorf("OSDiskSnapshotResourceID = %v, want %v", got, tt.wantSnapshotID)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateSnapshot_Cleanup_skipped(t *testing.T) {
|
||||
m := compute.NewSnapshotsClient("subscriptionId")
|
||||
m.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
t.Fatalf("clean up should be skipped, did not expect HTTP calls")
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
SnapshotsClientMock: m,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
|
||||
s := &StepCreateSnapshot{
|
||||
SkipCleanup: true,
|
||||
}
|
||||
s.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepCreateSnapshot_Cleanup(t *testing.T) {
|
||||
m := compute.NewSnapshotsClient("subscriptionId")
|
||||
{
|
||||
expectedCalls := []string{
|
||||
"POST /subscriptions/subscriptionId/resourceGroups/rg/providers/Microsoft.Compute/snapshots/snap1/endGetAccess?api-version=2019-07-01",
|
||||
"DELETE /subscriptions/subscriptionId/resourceGroups/rg/providers/Microsoft.Compute/snapshots/snap1?api-version=2019-07-01",
|
||||
}
|
||||
i := 0
|
||||
m.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
want := expectedCalls[i]
|
||||
got := r.Method + " " + r.URL.RequestURI()
|
||||
if want != got {
|
||||
t.Errorf("unexpected HTTP call: %v, wanted %v", got, want)
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
StatusCode: 599, // 500 is retried
|
||||
}, nil
|
||||
}
|
||||
i++
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
})
|
||||
}
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
SnapshotsClientMock: m,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
|
||||
s := &StepCreateSnapshot{
|
||||
ResourceID: "/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/snap1",
|
||||
Location: "region1",
|
||||
SkipCleanup: false,
|
||||
resourceGroup: "rg",
|
||||
snapshotName: "snap1",
|
||||
subscriptionID: "1234",
|
||||
}
|
||||
s.Cleanup(state)
|
||||
}
|
||||
45
builder/azure/chroot/step_resolve_plaform_image_version.go
Normal file
45
builder/azure/chroot/step_resolve_plaform_image_version.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// StepResolvePlatformImageVersion resolves the exact PIR version when the version is 'latest'
|
||||
type StepResolvePlatformImageVersion struct {
|
||||
*client.PlatformImage
|
||||
Location string
|
||||
}
|
||||
|
||||
// Run retrieves all available versions of a PIR image and stores the latest in the PlatformImage
|
||||
func (pi *StepResolvePlatformImageVersion) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if strings.EqualFold(pi.Version, "latest") {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
|
||||
vmi, err := azcli.VirtualMachineImagesClient().GetLatest(ctx, pi.Publisher, pi.Offer, pi.Sku, pi.Location)
|
||||
if err != nil {
|
||||
log.Printf("StepResolvePlatformImageVersion.Run: error: %+v", err)
|
||||
err := fmt.Errorf("error retieving latest version of %q: %v", pi.URN(), err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
pi.Version = to.String(vmi.Name)
|
||||
ui.Say("Resolved latest version of source image: " + pi.Version)
|
||||
} else {
|
||||
ui.Say("Nothing to do, version is not 'latest'")
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (*StepResolvePlatformImageVersion) Cleanup(multistep.StateBag) {}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
func TestStepResolvePlatformImageVersion_Run(t *testing.T) {
|
||||
|
||||
pi := &StepResolvePlatformImageVersion{
|
||||
PlatformImage: &client.PlatformImage{
|
||||
Version: "latest",
|
||||
}}
|
||||
|
||||
m := compute.NewVirtualMachineImagesClient("subscriptionId")
|
||||
m.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if !strings.Contains(r.URL.String(), "%24orderby=name+desc") {
|
||||
t.Errorf("Expected url to use odata based sorting, but got %q", r.URL.String())
|
||||
}
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(
|
||||
`[
|
||||
{"name":"1.2.3"},
|
||||
{"name":"4.5.6"}
|
||||
]`)),
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
})
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
VirtualMachineImagesClientMock: client.VirtualMachineImagesClient{
|
||||
VirtualMachineImagesClientAPI: m}})
|
||||
|
||||
ui, getErrs := testUI()
|
||||
state.Put("ui", ui)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
got := pi.Run(ctx, state)
|
||||
if got != multistep.ActionContinue {
|
||||
t.Errorf("Expected 'continue', but got %q", got)
|
||||
}
|
||||
|
||||
if pi.PlatformImage.Version != "1.2.3" {
|
||||
t.Errorf("Expected version '1.2.3', but got %q", pi.PlatformImage.Version)
|
||||
}
|
||||
|
||||
_ = getErrs
|
||||
}
|
||||
114
builder/azure/chroot/step_verify_shared_image_destination.go
Normal file
114
builder/azure/chroot/step_verify_shared_image_destination.go
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"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"
|
||||
)
|
||||
|
||||
var _ multistep.Step = &StepVerifySharedImageDestination{}
|
||||
|
||||
// StepVerifySharedImageDestination verifies that the shared image location matches the Location field in the step.
|
||||
// Also verifies that the OS Type is Linux.
|
||||
type StepVerifySharedImageDestination struct {
|
||||
Image SharedImageGalleryDestination
|
||||
Location string
|
||||
}
|
||||
|
||||
// Run retrieves the image metadata from Azure and compares the location to Location. Verifies the OS Type.
|
||||
func (s *StepVerifySharedImageDestination) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
errorMessage := func(message string, parameters ...interface{}) multistep.StepAction {
|
||||
err := fmt.Errorf(message, parameters...)
|
||||
log.Printf("StepVerifySharedImageDestination.Run: error: %+v", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
imageURI := fmt.Sprintf("/subscriptions/%s/resourcegroup/%s/providers/Microsoft.Compute/galleries/%s/images/%s",
|
||||
azcli.SubscriptionID(),
|
||||
s.Image.ResourceGroup,
|
||||
s.Image.GalleryName,
|
||||
s.Image.ImageName,
|
||||
)
|
||||
|
||||
ui.Say(fmt.Sprintf("Validating that shared image %s exists",
|
||||
imageURI))
|
||||
|
||||
image, err := azcli.GalleryImagesClient().Get(ctx,
|
||||
s.Image.ResourceGroup,
|
||||
s.Image.GalleryName,
|
||||
s.Image.ImageName)
|
||||
|
||||
if err != nil {
|
||||
return errorMessage("Error retrieving shared image %q: %+v ", imageURI, err)
|
||||
}
|
||||
|
||||
if image.ID == nil || *image.ID == "" {
|
||||
return errorMessage("Error retrieving shared image %q: ID field in response is empty", imageURI)
|
||||
}
|
||||
if image.GalleryImageProperties == nil {
|
||||
return errorMessage("Could not retrieve shared image properties for image %q.", to.String(image.ID))
|
||||
}
|
||||
|
||||
location := to.String(image.Location)
|
||||
|
||||
log.Printf("StepVerifySharedImageDestination:Run: Image %q, Location: %q, HvGen: %q, osState: %q",
|
||||
to.String(image.ID),
|
||||
location,
|
||||
image.GalleryImageProperties.HyperVGeneration,
|
||||
image.GalleryImageProperties.OsState)
|
||||
|
||||
if !strings.EqualFold(location, s.Location) {
|
||||
return errorMessage("Destination shared image resource %q is in a different location (%q) than this VM (%q). "+
|
||||
"Packer does not know how to handle that.",
|
||||
to.String(image.ID),
|
||||
location,
|
||||
s.Location)
|
||||
}
|
||||
|
||||
if image.GalleryImageProperties.OsType != compute.Linux {
|
||||
return errorMessage("The shared image (%q) is not a Linux image (found %q). Currently only Linux images are supported.",
|
||||
to.String(image.ID),
|
||||
image.GalleryImageProperties.OsType)
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Found image %s in location %s",
|
||||
to.String(image.ID),
|
||||
to.String(image.Location)))
|
||||
|
||||
versions, err := azcli.GalleryImageVersionsClient().ListByGalleryImageComplete(ctx,
|
||||
s.Image.ResourceGroup,
|
||||
s.Image.GalleryName,
|
||||
s.Image.ImageName)
|
||||
|
||||
for versions.NotDone() {
|
||||
version := versions.Value()
|
||||
|
||||
if version.Name == nil {
|
||||
return errorMessage("Could not retrieve versions for image %q: unexpected nil name", to.String(image.ID))
|
||||
}
|
||||
if *version.Name == s.Image.ImageVersion {
|
||||
return errorMessage("Shared image version %q already exists for image %q.", s.Image.ImageVersion, to.String(image.ID))
|
||||
}
|
||||
|
||||
err := versions.NextWithContext(ctx)
|
||||
if err != nil {
|
||||
return errorMessage("Could not retrieve versions for image %q: %+v", to.String(image.ID), err)
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (*StepVerifySharedImageDestination) Cleanup(multistep.StateBag) {}
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func TestStepVerifySharedImageDestination_Run(t *testing.T) {
|
||||
|
||||
type fields struct {
|
||||
Image SharedImageGalleryDestination
|
||||
Location string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want multistep.StepAction
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
want: multistep.ActionContinue,
|
||||
fields: fields{
|
||||
Image: SharedImageGalleryDestination{
|
||||
ResourceGroup: "rg",
|
||||
GalleryName: "gallery",
|
||||
ImageName: "image",
|
||||
ImageVersion: "1.2.3",
|
||||
},
|
||||
Location: "region1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
want: multistep.ActionHalt,
|
||||
wantErr: `Error retrieving shared image "/subscriptions/subscriptionID/resourcegroup/other-rg/providers/Microsoft.Compute/galleries/gallery/images/image": compute.GalleryImagesClient#Get: Failure responding to request: StatusCode=404 -- Original Error: autorest/azure: Service returned an error. Status=404 Code="NotFound" Message="Not found" `,
|
||||
fields: fields{
|
||||
Image: SharedImageGalleryDestination{
|
||||
ResourceGroup: "other-rg",
|
||||
GalleryName: "gallery",
|
||||
ImageName: "image",
|
||||
ImageVersion: "1.2.3",
|
||||
},
|
||||
Location: "region1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "wrong region",
|
||||
want: multistep.ActionHalt,
|
||||
wantErr: "Destination shared image resource \"image-resourceid-goes-here\" is in a different location (\"region1\") than this VM (\"other-region\"). Packer does not know how to handle that.",
|
||||
fields: fields{
|
||||
Image: SharedImageGalleryDestination{
|
||||
ResourceGroup: "rg",
|
||||
GalleryName: "gallery",
|
||||
ImageName: "image",
|
||||
ImageVersion: "1.2.3",
|
||||
},
|
||||
Location: "other-region",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "version exists",
|
||||
want: multistep.ActionHalt,
|
||||
wantErr: "Shared image version \"2.3.4\" already exists for image \"image-resourceid-goes-here\".",
|
||||
fields: fields{
|
||||
Image: SharedImageGalleryDestination{
|
||||
ResourceGroup: "rg",
|
||||
GalleryName: "gallery",
|
||||
ImageName: "image",
|
||||
ImageVersion: "2.3.4",
|
||||
},
|
||||
Location: "region1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not Linux",
|
||||
want: multistep.ActionHalt,
|
||||
wantErr: "The shared image (\"windows-image-resourceid-goes-here\") is not a Linux image (found \"Windows\"). Currently only Linux images are supported.",
|
||||
fields: fields{
|
||||
Image: SharedImageGalleryDestination{
|
||||
ResourceGroup: "rg",
|
||||
GalleryName: "gallery",
|
||||
ImageName: "windowsimage",
|
||||
ImageVersion: "1.2.3",
|
||||
},
|
||||
Location: "region1",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
gi := compute.NewGalleryImagesClient("subscriptionID")
|
||||
gi.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
switch {
|
||||
case r.Method == "GET" && strings.HasPrefix(r.URL.RequestURI(),
|
||||
"/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/galleries/gallery/images/image"):
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{
|
||||
"id": "image-resourceid-goes-here",
|
||||
"location": "region1",
|
||||
"properties": {
|
||||
"osType": "Linux"
|
||||
}
|
||||
}`)),
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
case r.Method == "GET" && strings.HasPrefix(r.URL.RequestURI(),
|
||||
"/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/galleries/gallery/images/windowsimage"):
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{
|
||||
"id": "windows-image-resourceid-goes-here",
|
||||
"location": "region1",
|
||||
"properties": {
|
||||
"osType": "Windows"
|
||||
}
|
||||
}`)),
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
}
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{
|
||||
"Code": "NotFound",
|
||||
"Message": "Not found"
|
||||
}`)),
|
||||
StatusCode: 404,
|
||||
}, nil
|
||||
})
|
||||
|
||||
giv := compute.NewGalleryImageVersionsClient("subscriptionID")
|
||||
giv.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if !(r.Method == "GET" && strings.HasPrefix(r.URL.RequestURI(),
|
||||
"/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/galleries/gallery/images/image/versions")) {
|
||||
t.Errorf("Unexpected HTTP call: %s %s", r.Method, r.URL.RequestURI())
|
||||
}
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{
|
||||
"value": [
|
||||
{
|
||||
"name": "2.3.4"
|
||||
}
|
||||
]
|
||||
}`)),
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
})
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
SubscriptionIDMock: "subscriptionID",
|
||||
GalleryImagesClientMock: gi,
|
||||
GalleryImageVersionsClientMock: giv,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StepVerifySharedImageDestination{
|
||||
Image: tt.fields.Image,
|
||||
Location: tt.fields.Location,
|
||||
}
|
||||
if got := s.Run(context.TODO(), state); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("StepVerifySharedImageDestination.Run() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
if err, ok := state.GetOk("error"); ok {
|
||||
if err.(error).Error() != tt.wantErr {
|
||||
t.Errorf("Unexpected error, got: %q, want: %q", err, tt.wantErr)
|
||||
}
|
||||
} else if tt.wantErr != "" {
|
||||
t.Errorf("Expected error, but didn't get any")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ import (
|
|||
)
|
||||
|
||||
type StepVerifySourceDisk struct {
|
||||
SubscriptionID string
|
||||
SourceDiskResourceID string
|
||||
Location string
|
||||
}
|
||||
|
|
@ -34,10 +33,10 @@ func (s StepVerifySourceDisk) Run(ctx context.Context, state multistep.StateBag)
|
|||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if !strings.EqualFold(resource.SubscriptionID, s.SubscriptionID) {
|
||||
if !strings.EqualFold(resource.SubscriptionID, azcli.SubscriptionID()) {
|
||||
err := fmt.Errorf("Source disk resource %q is in a different subscription than this VM (%q). "+
|
||||
"Packer does not know how to handle that.",
|
||||
s.SourceDiskResourceID, s.SubscriptionID)
|
||||
s.SourceDiskResourceID, azcli.SubscriptionID())
|
||||
log.Printf("StepVerifySourceDisk.Run: error: %+v", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
|
|
@ -18,7 +18,6 @@ import (
|
|||
|
||||
func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
||||
type fields struct {
|
||||
SubscriptionID string
|
||||
SourceDiskResourceID string
|
||||
Location string
|
||||
|
||||
|
|
@ -38,7 +37,6 @@ func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
|||
{
|
||||
name: "HappyPath",
|
||||
fields: fields{
|
||||
SubscriptionID: "subid1",
|
||||
SourceDiskResourceID: "/subscriptions/subid1/resourcegroups/rg1/providers/Microsoft.Compute/disks/disk1",
|
||||
Location: "westus2",
|
||||
|
||||
|
|
@ -50,7 +48,6 @@ func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
|||
{
|
||||
name: "NotAResourceID",
|
||||
fields: fields{
|
||||
SubscriptionID: "subid1",
|
||||
SourceDiskResourceID: "/other",
|
||||
Location: "westus2",
|
||||
|
||||
|
|
@ -63,7 +60,6 @@ func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
|||
{
|
||||
name: "DiskNotFound",
|
||||
fields: fields{
|
||||
SubscriptionID: "subid1",
|
||||
SourceDiskResourceID: "/subscriptions/subid1/resourcegroups/rg1/providers/Microsoft.Compute/disks/disk1",
|
||||
Location: "westus2",
|
||||
|
||||
|
|
@ -76,7 +72,6 @@ func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
|||
{
|
||||
name: "NotADisk",
|
||||
fields: fields{
|
||||
SubscriptionID: "subid1",
|
||||
SourceDiskResourceID: "/subscriptions/subid1/resourcegroups/rg1/providers/Microsoft.Compute/images/image1",
|
||||
Location: "westus2",
|
||||
|
||||
|
|
@ -88,7 +83,6 @@ func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
|||
{
|
||||
name: "OtherSubscription",
|
||||
fields: fields{
|
||||
SubscriptionID: "subid1",
|
||||
SourceDiskResourceID: "/subscriptions/subid2/resourcegroups/rg1/providers/Microsoft.Compute/disks/disk1",
|
||||
Location: "westus2",
|
||||
|
||||
|
|
@ -101,7 +95,6 @@ func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
|||
{
|
||||
name: "OtherLocation",
|
||||
fields: fields{
|
||||
SubscriptionID: "subid1",
|
||||
SourceDiskResourceID: "/subscriptions/subid1/resourcegroups/rg1/providers/Microsoft.Compute/disks/disk1",
|
||||
Location: "eastus",
|
||||
|
||||
|
|
@ -115,7 +108,6 @@ func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := StepVerifySourceDisk{
|
||||
SubscriptionID: tt.fields.SubscriptionID,
|
||||
SourceDiskResourceID: tt.fields.SourceDiskResourceID,
|
||||
Location: tt.fields.Location,
|
||||
}
|
||||
|
|
@ -129,16 +121,12 @@ func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
|||
}, nil
|
||||
})
|
||||
|
||||
errorBuffer := &strings.Builder{}
|
||||
ui := &packer.BasicUi{
|
||||
Reader: strings.NewReader(""),
|
||||
Writer: ioutil.Discard,
|
||||
ErrorWriter: errorBuffer,
|
||||
}
|
||||
ui, getErr := testUI()
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
DisksClientMock: m,
|
||||
DisksClientMock: m,
|
||||
SubscriptionIDMock: "subid1",
|
||||
})
|
||||
state.Put("ui", ui)
|
||||
|
||||
|
|
@ -148,8 +136,9 @@ func Test_StepVerifySourceDisk_Run(t *testing.T) {
|
|||
}
|
||||
|
||||
if tt.errormatch != "" {
|
||||
if !regexp.MustCompile(tt.errormatch).MatchString(errorBuffer.String()) {
|
||||
t.Errorf("Expected the error output (%q) to match %q", errorBuffer.String(), tt.errormatch)
|
||||
errs := getErr()
|
||||
if !regexp.MustCompile(tt.errormatch).MatchString(errs) {
|
||||
t.Errorf("Expected the error output (%q) to match %q", errs, tt.errormatch)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
21
builder/azure/common/artifact_test.go
Normal file
21
builder/azure/common/artifact_test.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArtifact_String(t *testing.T) {
|
||||
a := &Artifact{
|
||||
Resources: []string{
|
||||
"/subscriptions/4674464f-6024-43ae-903c-f6eed761be04/resourceGroups/rg/providers/Microsoft.Compute/disks/PackerTemp-osdisk-1586461959",
|
||||
"/subscriptions/4674464f-6024-43ae-903c-f6eed761be04/resourceGroups/images/providers/Microsoft.Compute/galleries/testgallery/images/myUbuntu/versions/1.0.10",
|
||||
},
|
||||
}
|
||||
want := `Azure resources created:
|
||||
/subscriptions/4674464f-6024-43ae-903c-f6eed761be04/resourcegroups/images/providers/microsoft.compute/galleries/testgallery/images/myubuntu/versions/1.0.10
|
||||
/subscriptions/4674464f-6024-43ae-903c-f6eed761be04/resourcegroups/rg/providers/microsoft.compute/disks/packertemp-osdisk-1586461959
|
||||
`
|
||||
if got := a.String(); got != want {
|
||||
t.Errorf("Artifact.String() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,21 +5,30 @@ import (
|
|||
"regexp"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
"github.com/hashicorp/packer/helper/useragent"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute/computeapi"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
type AzureClientSet interface {
|
||||
MetadataClient() MetadataClientAPI
|
||||
|
||||
DisksClient() computeapi.DisksClientAPI
|
||||
SnapshotsClient() computeapi.SnapshotsClientAPI
|
||||
ImagesClient() computeapi.ImagesClientAPI
|
||||
|
||||
GalleryImagesClient() computeapi.GalleryImagesClientAPI
|
||||
GalleryImageVersionsClient() computeapi.GalleryImageVersionsClientAPI
|
||||
|
||||
VirtualMachinesClient() computeapi.VirtualMachinesClientAPI
|
||||
VirtualMachineImagesClient() VirtualMachineImagesClientAPI
|
||||
|
||||
PollClient() autorest.Client
|
||||
|
||||
// SubscriptionID returns the subscription ID that this client set was created for
|
||||
SubscriptionID() string
|
||||
}
|
||||
|
||||
var subscriptionPathRegex = regexp.MustCompile(`/subscriptions/([[:xdigit:]]{8}(-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12})`)
|
||||
|
|
@ -50,6 +59,10 @@ func new(c Config, say func(string)) (*azureClientSet, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s azureClientSet) SubscriptionID() string {
|
||||
return s.subscriptionID
|
||||
}
|
||||
|
||||
func (s azureClientSet) configureAutorestClient(c *autorest.Client) {
|
||||
c.AddToUserAgent(useragent.String())
|
||||
c.Authorizer = s.authorizer
|
||||
|
|
@ -70,6 +83,13 @@ func (s azureClientSet) DisksClient() computeapi.DisksClientAPI {
|
|||
return c
|
||||
}
|
||||
|
||||
func (s azureClientSet) SnapshotsClient() computeapi.SnapshotsClientAPI {
|
||||
c := compute.NewSnapshotsClient(s.subscriptionID)
|
||||
s.configureAutorestClient(&c.Client)
|
||||
c.PollingDelay = s.PollingDelay
|
||||
return c
|
||||
}
|
||||
|
||||
func (s azureClientSet) ImagesClient() computeapi.ImagesClientAPI {
|
||||
c := compute.NewImagesClient(s.subscriptionID)
|
||||
s.configureAutorestClient(&c.Client)
|
||||
|
|
@ -88,12 +108,26 @@ func (s azureClientSet) VirtualMachineImagesClient() VirtualMachineImagesClientA
|
|||
c := compute.NewVirtualMachineImagesClient(s.subscriptionID)
|
||||
s.configureAutorestClient(&c.Client)
|
||||
c.PollingDelay = s.PollingDelay
|
||||
return virtualMachineImagesClientAPI{c}
|
||||
return VirtualMachineImagesClient{c}
|
||||
}
|
||||
|
||||
func (s azureClientSet) GalleryImagesClient() computeapi.GalleryImagesClientAPI {
|
||||
c := compute.NewGalleryImagesClient(s.subscriptionID)
|
||||
s.configureAutorestClient(&c.Client)
|
||||
c.PollingDelay = s.PollingDelay
|
||||
return c
|
||||
}
|
||||
|
||||
func (s azureClientSet) GalleryImageVersionsClient() computeapi.GalleryImageVersionsClientAPI {
|
||||
c := compute.NewGalleryImageVersionsClient(s.subscriptionID)
|
||||
s.configureAutorestClient(&c.Client)
|
||||
c.PollingDelay = s.PollingDelay
|
||||
return c
|
||||
}
|
||||
|
||||
func (s azureClientSet) PollClient() autorest.Client {
|
||||
c := autorest.NewClientWithUserAgent("Packer-Azure-ClientSet")
|
||||
s.configureAutorestClient(&c)
|
||||
c.PollingDelay = time.Second / 3
|
||||
c.PollingDelay = time.Second * 5
|
||||
return c
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,24 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute/computeapi"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute/computeapi"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
var _ AzureClientSet = &AzureClientSetMock{}
|
||||
|
||||
// AzureClientSetMock provides a generic mock for AzureClientSet
|
||||
type AzureClientSetMock struct {
|
||||
DisksClientMock computeapi.DisksClientAPI
|
||||
SnapshotsClientMock computeapi.SnapshotsClientAPI
|
||||
ImagesClientMock computeapi.ImagesClientAPI
|
||||
VirtualMachineImagesClientMock VirtualMachineImagesClientAPI
|
||||
VirtualMachinesClientMock computeapi.VirtualMachinesClientAPI
|
||||
GalleryImagesClientMock computeapi.GalleryImagesClientAPI
|
||||
GalleryImageVersionsClientMock computeapi.GalleryImageVersionsClientAPI
|
||||
PollClientMock autorest.Client
|
||||
MetadataClientMock MetadataClientAPI
|
||||
SubscriptionIDMock string
|
||||
}
|
||||
|
||||
// DisksClient returns a DisksClientAPI
|
||||
|
|
@ -20,6 +26,11 @@ func (m *AzureClientSetMock) DisksClient() computeapi.DisksClientAPI {
|
|||
return m.DisksClientMock
|
||||
}
|
||||
|
||||
// SnapshotsClient returns a SnapshotsClientAPI
|
||||
func (m *AzureClientSetMock) SnapshotsClient() computeapi.SnapshotsClientAPI {
|
||||
return m.SnapshotsClientMock
|
||||
}
|
||||
|
||||
// ImagesClient returns a ImagesClientAPI
|
||||
func (m *AzureClientSetMock) ImagesClient() computeapi.ImagesClientAPI {
|
||||
return m.ImagesClientMock
|
||||
|
|
@ -35,6 +46,16 @@ func (m *AzureClientSetMock) VirtualMachinesClient() computeapi.VirtualMachinesC
|
|||
return m.VirtualMachinesClientMock
|
||||
}
|
||||
|
||||
// GalleryImagesClient returns a GalleryImagesClientAPI
|
||||
func (m *AzureClientSetMock) GalleryImagesClient() computeapi.GalleryImagesClientAPI {
|
||||
return m.GalleryImagesClientMock
|
||||
}
|
||||
|
||||
// GalleryImageVersionsClient returns a GalleryImageVersionsClientAPI
|
||||
func (m *AzureClientSetMock) GalleryImageVersionsClient() computeapi.GalleryImageVersionsClientAPI {
|
||||
return m.GalleryImageVersionsClientMock
|
||||
}
|
||||
|
||||
// PollClient returns an autorest Client that can be used for polling async requests
|
||||
func (m *AzureClientSetMock) PollClient() autorest.Client {
|
||||
return m.PollClientMock
|
||||
|
|
@ -44,3 +65,8 @@ func (m *AzureClientSetMock) PollClient() autorest.Client {
|
|||
func (m *AzureClientSetMock) MetadataClient() MetadataClientAPI {
|
||||
return m.MetadataClientMock
|
||||
}
|
||||
|
||||
// SubscriptionID returns SubscriptionIDMock
|
||||
func (m *AzureClientSetMock) SubscriptionID() string {
|
||||
return m.SubscriptionIDMock
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,22 @@ import (
|
|||
// DefaultMetadataClient is the default instance metadata client for Azure. Replace this variable for testing purposes only
|
||||
var DefaultMetadataClient = NewMetadataClient()
|
||||
|
||||
// MetadataClient holds methods that Packer uses to get information about the current VM
|
||||
// MetadataClientAPI holds methods that Packer uses to get information about the current VM
|
||||
type MetadataClientAPI interface {
|
||||
GetComputeInfo() (*ComputeInfo, error)
|
||||
}
|
||||
|
||||
// MetadataClientStub is an easy way to put a test hook in DefaultMetadataClient
|
||||
type MetadataClientStub struct {
|
||||
ComputeInfo
|
||||
}
|
||||
|
||||
//GetComputeInfo implements MetadataClientAPI
|
||||
func (s MetadataClientStub) GetComputeInfo() (*ComputeInfo, error) {
|
||||
return &s.ComputeInfo, nil
|
||||
}
|
||||
|
||||
// ComputeInfo defines the Azure VM metadata that is used in Packer
|
||||
type ComputeInfo struct {
|
||||
Name string
|
||||
ResourceGroupName string
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import (
|
|||
"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/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute/computeapi"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
)
|
||||
|
||||
|
|
@ -19,9 +19,9 @@ type VirtualMachineImagesClientAPI interface {
|
|||
GetLatest(ctx context.Context, publisher, offer, sku, location string) (*compute.VirtualMachineImageResource, error)
|
||||
}
|
||||
|
||||
var _ VirtualMachineImagesClientAPI = virtualMachineImagesClientAPI{}
|
||||
var _ VirtualMachineImagesClientAPI = VirtualMachineImagesClient{}
|
||||
|
||||
type virtualMachineImagesClientAPI struct {
|
||||
type VirtualMachineImagesClient struct {
|
||||
computeapi.VirtualMachineImagesClientAPI
|
||||
}
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ func ParsePlatformImageURN(urn string) (image *PlatformImage, err error) {
|
|||
return &PlatformImage{parts[0], parts[1], parts[2], parts[3]}, nil
|
||||
}
|
||||
|
||||
func (c virtualMachineImagesClientAPI) GetLatest(ctx context.Context, publisher, offer, sku, location string) (*compute.VirtualMachineImageResource, error) {
|
||||
func (c VirtualMachineImagesClient) GetLatest(ctx context.Context, publisher, offer, sku, location string) (*compute.VirtualMachineImageResource, error) {
|
||||
result, err := c.List(ctx, location, publisher, offer, sku, "", to.Int32Ptr(1), "name desc")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
13
builder/azure/common/strings_contains.go
Normal file
13
builder/azure/common/strings_contains.go
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
package common
|
||||
|
||||
import "strings"
|
||||
|
||||
// StringsContains returns true if the `haystack` contains the `needle`. Search is case insensitive.
|
||||
func StringsContains(haystack []string, needle string) bool {
|
||||
for _, s := range haystack {
|
||||
if strings.EqualFold(s, needle) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
39
builder/azure/common/strings_contains_test.go
Normal file
39
builder/azure/common/strings_contains_test.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package common
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestStringsContains(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
haystack []string
|
||||
needle string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "found",
|
||||
haystack: []string{"a", "b", "c"},
|
||||
needle: "b",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "missing",
|
||||
haystack: []string{"a", "b", "c"},
|
||||
needle: "D",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "case insensitive",
|
||||
haystack: []string{"a", "b", "c"},
|
||||
needle: "B",
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := StringsContains(tt.haystack, tt.needle); got != tt.want {
|
||||
t.Errorf("StringsContains() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -145,7 +145,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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},
|
||||
|
|
@ -172,7 +172,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"managed_image_resource_group_name": &hcldec.AttrSpec{Name: "managed_image_resource_group_name", Type: cty.String, Required: false},
|
||||
"managed_image_name": &hcldec.AttrSpec{Name: "managed_image_name", Type: cty.String, Required: false},
|
||||
"managed_image_storage_account_type": &hcldec.AttrSpec{Name: "managed_image_storage_account_type", Type: cty.String, Required: false},
|
||||
"azure_tags": &hcldec.BlockAttrsSpec{TypeName: "azure_tags", ElementType: cty.String, Required: false},
|
||||
"azure_tags": &hcldec.AttrSpec{Name: "azure_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"plan_id": &hcldec.AttrSpec{Name: "plan_id", Type: cty.String, Required: false},
|
||||
"polling_duration_timeout": &hcldec.AttrSpec{Name: "polling_duration_timeout", Type: cty.String, Required: false},
|
||||
"os_type": &hcldec.AttrSpec{Name: "os_type", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
@ -204,7 +204,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"template_requires_hvm": &hcldec.AttrSpec{Name: "template_requires_hvm", Type: cty.Bool, Required: false},
|
||||
"template_scalable": &hcldec.AttrSpec{Name: "template_scalable", Type: cty.Bool, Required: false},
|
||||
"template_tag": &hcldec.AttrSpec{Name: "template_tag", Type: cty.String, Required: false},
|
||||
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
@ -157,7 +157,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"pty": &hcldec.AttrSpec{Name: "pty", Type: cty.Bool, Required: false},
|
||||
"pull": &hcldec.AttrSpec{Name: "pull", Type: cty.Bool, Required: false},
|
||||
"run_command": &hcldec.AttrSpec{Name: "run_command", Type: cty.List(cty.String), Required: false},
|
||||
"volumes": &hcldec.BlockAttrsSpec{TypeName: "volumes", ElementType: cty.String, Required: false},
|
||||
"volumes": &hcldec.AttrSpec{Name: "volumes", Type: cty.Map(cty.String), Required: false},
|
||||
"fix_upload_owner": &hcldec.AttrSpec{Name: "fix_upload_owner", Type: cty.Bool, Required: false},
|
||||
"windows_container": &hcldec.AttrSpec{Name: "windows_container", Type: cty.Bool, Required: false},
|
||||
"login": &hcldec.AttrSpec{Name: "login", Type: cty.Bool, Required: false},
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"source": &hcldec.AttrSpec{Name: "source", Type: cty.String, Required: false},
|
||||
"target": &hcldec.AttrSpec{Name: "target", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
@ -171,13 +171,13 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false},
|
||||
"image_encryption_key": &hcldec.BlockSpec{TypeName: "image_encryption_key", Nested: hcldec.ObjectSpec((*FlatCustomerEncryptionKey)(nil).HCL2Spec())},
|
||||
"image_family": &hcldec.AttrSpec{Name: "image_family", Type: cty.String, Required: false},
|
||||
"image_labels": &hcldec.BlockAttrsSpec{TypeName: "image_labels", ElementType: cty.String, Required: false},
|
||||
"image_labels": &hcldec.AttrSpec{Name: "image_labels", Type: cty.Map(cty.String), Required: false},
|
||||
"image_licenses": &hcldec.AttrSpec{Name: "image_licenses", Type: cty.List(cty.String), Required: false},
|
||||
"instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false},
|
||||
"labels": &hcldec.BlockAttrsSpec{TypeName: "labels", ElementType: cty.String, Required: false},
|
||||
"labels": &hcldec.AttrSpec{Name: "labels", Type: cty.Map(cty.String), Required: false},
|
||||
"machine_type": &hcldec.AttrSpec{Name: "machine_type", Type: cty.String, Required: false},
|
||||
"metadata": &hcldec.BlockAttrsSpec{TypeName: "metadata", ElementType: cty.String, Required: false},
|
||||
"metadata_files": &hcldec.BlockAttrsSpec{TypeName: "metadata_files", ElementType: cty.String, Required: false},
|
||||
"metadata": &hcldec.AttrSpec{Name: "metadata", Type: cty.Map(cty.String), Required: false},
|
||||
"metadata_files": &hcldec.AttrSpec{Name: "metadata_files", Type: cty.Map(cty.String), Required: false},
|
||||
"min_cpu_platform": &hcldec.AttrSpec{Name: "min_cpu_platform", Type: cty.String, Required: false},
|
||||
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
||||
"network_project_id": &hcldec.AttrSpec{Name: "network_project_id", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
@ -142,7 +142,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"image": &hcldec.AttrSpec{Name: "image", Type: cty.String, Required: false},
|
||||
"image_filter": &hcldec.BlockSpec{TypeName: "image_filter", Nested: hcldec.ObjectSpec((*FlatimageFilter)(nil).HCL2Spec())},
|
||||
"snapshot_name": &hcldec.AttrSpec{Name: "snapshot_name", Type: cty.String, Required: false},
|
||||
"snapshot_labels": &hcldec.BlockAttrsSpec{TypeName: "snapshot_labels", ElementType: cty.String, Required: false},
|
||||
"snapshot_labels": &hcldec.AttrSpec{Name: "snapshot_labels", Type: cty.Map(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},
|
||||
"ssh_keys": &hcldec.AttrSpec{Name: "ssh_keys", Type: cty.List(cty.String), Required: false},
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
@ -163,12 +163,12 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"source_image": &hcldec.AttrSpec{Name: "source_image", Type: cty.String, Required: false},
|
||||
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
|
||||
"image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false},
|
||||
"image_tags": &hcldec.BlockAttrsSpec{TypeName: "image_tags", ElementType: cty.String, Required: false},
|
||||
"image_tags": &hcldec.AttrSpec{Name: "image_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"image_tag": &hcldec.BlockListSpec{TypeName: "image_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"image_service": &hcldec.AttrSpec{Name: "image_service", Type: cty.String, Required: false},
|
||||
"vm_type": &hcldec.AttrSpec{Name: "vm_type", Type: cty.String, Required: false},
|
||||
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
|
||||
"vm_tags": &hcldec.BlockAttrsSpec{TypeName: "vm_tags", ElementType: cty.String, Required: false},
|
||||
"vm_tags": &hcldec.AttrSpec{Name: "vm_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"vm_tag": &hcldec.BlockListSpec{TypeName: "vm_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"disk_name": &hcldec.AttrSpec{Name: "disk_name", Type: cty.String, Required: false},
|
||||
"disk_type": &hcldec.AttrSpec{Name: "disk_type", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"config_file": &hcldec.AttrSpec{Name: "config_file", Type: cty.String, Required: false},
|
||||
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"output_image": &hcldec.AttrSpec{Name: "output_image", Type: cty.String, Required: false},
|
||||
"container_name": &hcldec.AttrSpec{Name: "container_name", Type: cty.String, Required: false},
|
||||
|
|
@ -51,8 +51,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"image": &hcldec.AttrSpec{Name: "image", Type: cty.String, Required: false},
|
||||
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
|
||||
"init_sleep": &hcldec.AttrSpec{Name: "init_sleep", Type: cty.String, Required: false},
|
||||
"publish_properties": &hcldec.BlockAttrsSpec{TypeName: "publish_properties", ElementType: cty.String, Required: false},
|
||||
"launch_config": &hcldec.BlockAttrsSpec{TypeName: "launch_config", ElementType: cty.String, Required: false},
|
||||
"publish_properties": &hcldec.AttrSpec{Name: "publish_properties", Type: cty.Map(cty.String), Required: false},
|
||||
"launch_config": &hcldec.AttrSpec{Name: "launch_config", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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},
|
||||
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false},
|
||||
"user_id": &hcldec.AttrSpec{Name: "user_id", Type: cty.String, Required: false},
|
||||
|
|
@ -156,7 +156,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"application_credential_secret": &hcldec.AttrSpec{Name: "application_credential_secret", Type: cty.String, Required: false},
|
||||
"cloud": &hcldec.AttrSpec{Name: "cloud", Type: cty.String, Required: false},
|
||||
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
|
||||
"metadata": &hcldec.BlockAttrsSpec{TypeName: "metadata", ElementType: cty.String, Required: false},
|
||||
"metadata": &hcldec.AttrSpec{Name: "metadata", Type: cty.Map(cty.String), Required: false},
|
||||
"image_visibility": &hcldec.AttrSpec{Name: "image_visibility", Type: cty.String, Required: false},
|
||||
"image_members": &hcldec.AttrSpec{Name: "image_members", Type: cty.List(cty.String), Required: false},
|
||||
"image_auto_accept_members": &hcldec.AttrSpec{Name: "image_auto_accept_members", Type: cty.Bool, Required: false},
|
||||
|
|
@ -223,7 +223,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false},
|
||||
"instance_metadata": &hcldec.BlockAttrsSpec{TypeName: "instance_metadata", ElementType: cty.String, Required: false},
|
||||
"instance_metadata": &hcldec.AttrSpec{Name: "instance_metadata", Type: cty.Map(cty.String), Required: false},
|
||||
"force_delete": &hcldec.AttrSpec{Name: "force_delete", Type: cty.Bool, Required: false},
|
||||
"config_drive": &hcldec.AttrSpec{Name: "config_drive", Type: cty.Bool, Required: false},
|
||||
"floating_ip_pool": &hcldec.AttrSpec{Name: "floating_ip_pool", Type: cty.String, Required: false},
|
||||
|
|
@ -289,7 +289,7 @@ func (*FlatImageFilterOptions) HCL2Spec() map[string]hcldec.Spec {
|
|||
"owner": &hcldec.AttrSpec{Name: "owner", Type: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.List(cty.String), Required: false},
|
||||
"visibility": &hcldec.AttrSpec{Name: "visibility", Type: cty.String, Required: false},
|
||||
"properties": &hcldec.BlockAttrsSpec{TypeName: "properties", ElementType: cty.String, Required: false},
|
||||
"properties": &hcldec.AttrSpec{Name: "properties", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"persistent_volume_size": &hcldec.AttrSpec{Name: "persistent_volume_size", Type: cty.Number, Required: false},
|
||||
"builder_upload_image_command": &hcldec.AttrSpec{Name: "builder_upload_image_command", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
@ -157,12 +157,12 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"shape": &hcldec.AttrSpec{Name: "shape", Type: cty.String, Required: false},
|
||||
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
|
||||
"instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false},
|
||||
"metadata": &hcldec.BlockAttrsSpec{TypeName: "metadata", ElementType: cty.String, Required: false},
|
||||
"metadata": &hcldec.AttrSpec{Name: "metadata", Type: cty.Map(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},
|
||||
"subnet_ocid": &hcldec.AttrSpec{Name: "subnet_ocid", Type: cty.String, Required: false},
|
||||
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
|
||||
"defined_tags": &hcldec.BlockAttrsSpec{TypeName: "defined_tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"defined_tags": &hcldec.AttrSpec{Name: "defined_tags", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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_oapi": &hcldec.AttrSpec{Name: "custom_endpoint_oapi", Type: cty.String, Required: false},
|
||||
|
|
@ -149,10 +149,10 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"omi_groups": &hcldec.AttrSpec{Name: "omi_groups", Type: cty.List(cty.String), Required: false},
|
||||
"omi_product_codes": &hcldec.AttrSpec{Name: "omi_product_codes", Type: cty.List(cty.String), Required: false},
|
||||
"omi_regions": &hcldec.AttrSpec{Name: "omi_regions", Type: cty.List(cty.String), Required: false},
|
||||
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), 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},
|
||||
"snapshot_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
|
||||
"snapshot_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_account_ids": &hcldec.AttrSpec{Name: "snapshot_account_ids", Type: cty.List(cty.String), Required: false},
|
||||
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
|
||||
"omi_block_device_mappings": &hcldec.BlockListSpec{TypeName: "omi_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
|
||||
|
|
@ -167,14 +167,14 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
|
||||
"vm_type": &hcldec.AttrSpec{Name: "vm_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},
|
||||
"run_tags": &hcldec.AttrSpec{Name: "run_tags", Type: cty.Map(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_omi": &hcldec.AttrSpec{Name: "source_omi", Type: cty.String, Required: false},
|
||||
"source_omi_filter": &hcldec.BlockSpec{TypeName: "source_omi_filter", Nested: hcldec.ObjectSpec((*common.FlatOmiFilterOptions)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"spot_tags": &hcldec.AttrSpec{Name: "spot_tags", Type: cty.Map(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},
|
||||
|
|
@ -225,7 +225,7 @@ 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},
|
||||
"run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "run_volume_tags", ElementType: cty.String, Required: false},
|
||||
"run_volume_tags": &hcldec.AttrSpec{Name: "run_volume_tags", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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_oapi": &hcldec.AttrSpec{Name: "custom_endpoint_oapi", Type: cty.String, Required: false},
|
||||
|
|
@ -153,14 +153,14 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
|
||||
"vm_type": &hcldec.AttrSpec{Name: "vm_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},
|
||||
"run_tags": &hcldec.AttrSpec{Name: "run_tags", Type: cty.Map(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_omi": &hcldec.AttrSpec{Name: "source_omi", Type: cty.String, Required: false},
|
||||
"source_omi_filter": &hcldec.BlockSpec{TypeName: "source_omi_filter", Nested: hcldec.ObjectSpec((*common.FlatOmiFilterOptions)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"spot_tags": &hcldec.AttrSpec{Name: "spot_tags", Type: cty.Map(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},
|
||||
|
|
@ -220,14 +220,14 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"omi_groups": &hcldec.AttrSpec{Name: "omi_groups", Type: cty.List(cty.String), Required: false},
|
||||
"omi_product_codes": &hcldec.AttrSpec{Name: "omi_product_codes", Type: cty.List(cty.String), Required: false},
|
||||
"omi_regions": &hcldec.AttrSpec{Name: "omi_regions", Type: cty.List(cty.String), Required: false},
|
||||
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), 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},
|
||||
"snapshot_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
|
||||
"snapshot_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_account_ids": &hcldec.AttrSpec{Name: "snapshot_account_ids", Type: cty.List(cty.String), Required: false},
|
||||
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
|
||||
"omi_root_device": &hcldec.BlockSpec{TypeName: "omi_root_device", Nested: hcldec.ObjectSpec((*FlatRootBlockDevice)(nil).HCL2Spec())},
|
||||
"run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "run_volume_tags", ElementType: cty.String, Required: false},
|
||||
"run_volume_tags": &hcldec.AttrSpec{Name: "run_volume_tags", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
@ -154,7 +154,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(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_oapi": &hcldec.AttrSpec{Name: "custom_endpoint_oapi", Type: cty.String, Required: false},
|
||||
|
|
@ -176,14 +176,14 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
|
||||
"vm_type": &hcldec.AttrSpec{Name: "vm_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},
|
||||
"run_tags": &hcldec.AttrSpec{Name: "run_tags", Type: cty.Map(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_omi": &hcldec.AttrSpec{Name: "source_omi", Type: cty.String, Required: false},
|
||||
"source_omi_filter": &hcldec.BlockSpec{TypeName: "source_omi_filter", Nested: hcldec.ObjectSpec((*common.FlatOmiFilterOptions)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"spot_tags": &hcldec.AttrSpec{Name: "spot_tags", Type: cty.Map(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},
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"omi_block_device_mappings": &hcldec.BlockListSpec{TypeName: "omi_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
|
||||
"omi_name": &hcldec.AttrSpec{Name: "omi_name", Type: cty.String, Required: false},
|
||||
|
|
@ -88,10 +88,10 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"omi_product_codes": &hcldec.AttrSpec{Name: "omi_product_codes", Type: cty.List(cty.String), Required: false},
|
||||
"omi_regions": &hcldec.AttrSpec{Name: "omi_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: "tags", ElementType: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), 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},
|
||||
"snapshot_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
|
||||
"snapshot_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_account_ids": &hcldec.AttrSpec{Name: "snapshot_account_ids", 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},
|
||||
|
|
@ -119,7 +119,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"root_volume_type": &hcldec.AttrSpec{Name: "root_volume_type", Type: cty.String, Required: false},
|
||||
"source_omi": &hcldec.AttrSpec{Name: "source_omi", Type: cty.String, Required: false},
|
||||
"source_omi_filter": &hcldec.BlockSpec{TypeName: "source_omi_filter", Nested: hcldec.ObjectSpec((*common.FlatOmiFilterOptions)(nil).HCL2Spec())},
|
||||
"root_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "root_volume_tags", ElementType: cty.String, Required: false},
|
||||
"root_volume_tags": &hcldec.AttrSpec{Name: "root_volume_tags", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ func (*NetFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcl
|
|||
// The decoded values from this spec will then be applied to a FlatNetFilterOptions.
|
||||
func (*FlatNetFilterOptions) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
|
||||
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
|
||||
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
|
|
@ -90,7 +90,7 @@ func (*OmiFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcl
|
|||
// The decoded values from this spec will then be applied to a FlatOmiFilterOptions.
|
||||
func (*FlatOmiFilterOptions) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
|
||||
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
|
||||
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"owners": &hcldec.AttrSpec{Name: "owners", Type: cty.List(cty.String), Required: false},
|
||||
"most_recent": &hcldec.AttrSpec{Name: "most_recent", Type: cty.Bool, Required: false},
|
||||
|
|
@ -117,7 +117,7 @@ func (*SecurityGroupFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[
|
|||
// 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},
|
||||
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
|
||||
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
|
|
@ -144,7 +144,7 @@ func (*SubnetFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]
|
|||
// 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},
|
||||
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
|
||||
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"most_free": &hcldec.AttrSpec{Name: "most_free", Type: cty.Bool, Required: false},
|
||||
"random": &hcldec.AttrSpec{Name: "random", Type: cty.Bool, Required: false},
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"floppy_files": &hcldec.AttrSpec{Name: "floppy_files", Type: cty.List(cty.String), Required: false},
|
||||
"floppy_dirs": &hcldec.AttrSpec{Name: "floppy_dirs", Type: cty.List(cty.String), Required: false},
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"secret_id": &hcldec.AttrSpec{Name: "secret_id", Type: cty.String, Required: false},
|
||||
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
|
||||
|
|
@ -150,7 +150,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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},
|
||||
"host_name": &hcldec.AttrSpec{Name: "host_name", Type: cty.String, Required: false},
|
||||
"run_tags": &hcldec.BlockAttrsSpec{TypeName: "run_tags", ElementType: cty.String, Required: false},
|
||||
"run_tags": &hcldec.AttrSpec{Name: "run_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_tag": &hcldec.BlockListSpec{TypeName: "run_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"triton_url": &hcldec.AttrSpec{Name: "triton_url", Type: cty.String, Required: false},
|
||||
"triton_account": &hcldec.AttrSpec{Name: "triton_account", Type: cty.String, Required: false},
|
||||
|
|
@ -112,8 +112,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"source_machine_package": &hcldec.AttrSpec{Name: "source_machine_package", Type: cty.String, Required: false},
|
||||
"source_machine_image": &hcldec.AttrSpec{Name: "source_machine_image", Type: cty.String, Required: false},
|
||||
"source_machine_networks": &hcldec.AttrSpec{Name: "source_machine_networks", Type: cty.List(cty.String), Required: false},
|
||||
"source_machine_metadata": &hcldec.BlockAttrsSpec{TypeName: "source_machine_metadata", ElementType: cty.String, Required: false},
|
||||
"source_machine_tags": &hcldec.BlockAttrsSpec{TypeName: "source_machine_tags", ElementType: cty.String, Required: false},
|
||||
"source_machine_metadata": &hcldec.AttrSpec{Name: "source_machine_metadata", Type: cty.Map(cty.String), Required: false},
|
||||
"source_machine_tags": &hcldec.AttrSpec{Name: "source_machine_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"source_machine_tag": &hcldec.BlockListSpec{TypeName: "source_machine_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"source_machine_firewall_enabled": &hcldec.AttrSpec{Name: "source_machine_firewall_enabled", Type: cty.Bool, Required: false},
|
||||
"source_machine_image_filter": &hcldec.BlockSpec{TypeName: "source_machine_image_filter", Nested: hcldec.ObjectSpec((*FlatMachineImageFilter)(nil).HCL2Spec())},
|
||||
|
|
@ -123,7 +123,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"image_homepage": &hcldec.AttrSpec{Name: "image_homepage", Type: cty.String, Required: false},
|
||||
"image_eula_url": &hcldec.AttrSpec{Name: "image_eula_url", Type: cty.String, Required: false},
|
||||
"image_acls": &hcldec.AttrSpec{Name: "image_acls", Type: cty.List(cty.String), Required: false},
|
||||
"image_tags": &hcldec.BlockAttrsSpec{TypeName: "image_tags", ElementType: cty.String, Required: false},
|
||||
"image_tags": &hcldec.AttrSpec{Name: "image_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"image_tag": &hcldec.BlockListSpec{TypeName: "image_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"public_key": &hcldec.AttrSpec{Name: "public_key", Type: cty.String, Required: false},
|
||||
"private_key": &hcldec.AttrSpec{Name: "private_key", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
|
|||
|
|
@ -144,12 +144,13 @@ func NewDriver(dconfig *DriverConfig, config *SSHConfig, vmName string) (Driver,
|
|||
errs := ""
|
||||
for _, driver := range drivers {
|
||||
err := driver.Verify()
|
||||
log.Printf("Testing vmware driver %T. Success: %t",
|
||||
driver, err == nil)
|
||||
|
||||
log.Printf("Testing against vmware driver %T, Success: %t", driver, err == nil)
|
||||
if err == nil {
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
log.Printf("skipping %T because it failed with the following error %s", driver, err)
|
||||
errs += "* " + err.Error() + "\n"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@ type RunConfig struct {
|
|||
// this value is set to true, the machine will start without a console. For
|
||||
// VMware machines, Packer will output VNC connection information in case you
|
||||
// need to connect to the console to debug the build process.
|
||||
// Some users have experienced issues where Packer cannot properly connect
|
||||
// to a VM if it is headless; this appears to be a result of not ever having
|
||||
// launched the VMWare GUI and accepting the evaluation license, or
|
||||
// supplying a real license. If you experience this, launching VMWare and
|
||||
// accepting the license should resolve your problem.
|
||||
Headless bool `mapstructure:"headless" required:"false"`
|
||||
// The IP address that should be
|
||||
// binded to for VNC. By default packer will use 127.0.0.1 for this. If you
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
@ -239,8 +239,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"ssh_skip_request_pty": &hcldec.AttrSpec{Name: "ssh_skip_request_pty", Type: cty.Bool, Required: false},
|
||||
"tools_upload_flavor": &hcldec.AttrSpec{Name: "tools_upload_flavor", Type: cty.String, Required: false},
|
||||
"tools_upload_path": &hcldec.AttrSpec{Name: "tools_upload_path", Type: cty.String, Required: false},
|
||||
"vmx_data": &hcldec.BlockAttrsSpec{TypeName: "vmx_data", ElementType: cty.String, Required: false},
|
||||
"vmx_data_post": &hcldec.BlockAttrsSpec{TypeName: "vmx_data_post", ElementType: cty.String, Required: false},
|
||||
"vmx_data": &hcldec.AttrSpec{Name: "vmx_data", Type: cty.Map(cty.String), Required: false},
|
||||
"vmx_data_post": &hcldec.AttrSpec{Name: "vmx_data_post", Type: cty.Map(cty.String), Required: false},
|
||||
"vmx_remove_ethernet_interfaces": &hcldec.AttrSpec{Name: "vmx_remove_ethernet_interfaces", Type: cty.Bool, Required: false},
|
||||
"display_name": &hcldec.AttrSpec{Name: "display_name", Type: cty.String, Required: false},
|
||||
"format": &hcldec.AttrSpec{Name: "format", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
@ -199,8 +199,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"ssh_skip_request_pty": &hcldec.AttrSpec{Name: "ssh_skip_request_pty", Type: cty.Bool, Required: false},
|
||||
"tools_upload_flavor": &hcldec.AttrSpec{Name: "tools_upload_flavor", Type: cty.String, Required: false},
|
||||
"tools_upload_path": &hcldec.AttrSpec{Name: "tools_upload_path", Type: cty.String, Required: false},
|
||||
"vmx_data": &hcldec.BlockAttrsSpec{TypeName: "vmx_data", ElementType: cty.String, Required: false},
|
||||
"vmx_data_post": &hcldec.BlockAttrsSpec{TypeName: "vmx_data_post", ElementType: cty.String, Required: false},
|
||||
"vmx_data": &hcldec.AttrSpec{Name: "vmx_data", Type: cty.Map(cty.String), Required: false},
|
||||
"vmx_data_post": &hcldec.AttrSpec{Name: "vmx_data_post", Type: cty.Map(cty.String), Required: false},
|
||||
"vmx_remove_ethernet_interfaces": &hcldec.AttrSpec{Name: "vmx_remove_ethernet_interfaces", Type: cty.Bool, Required: false},
|
||||
"display_name": &hcldec.AttrSpec{Name: "display_name", Type: cty.String, Required: false},
|
||||
"format": &hcldec.AttrSpec{Name: "format", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ type FlatConfig struct {
|
|||
VideoRAM *int64 `mapstructure:"video_ram" cty:"video_ram"`
|
||||
VGPUProfile *string `mapstructure:"vgpu_profile" cty:"vgpu_profile"`
|
||||
NestedHV *bool `mapstructure:"NestedHV" cty:"NestedHV"`
|
||||
Firmware *string `mapstructure:"firmware" cty:"firmware"`
|
||||
ConfigParams map[string]string `mapstructure:"configuration_parameters" cty:"configuration_parameters"`
|
||||
BootOrder *string `mapstructure:"boot_order" cty:"boot_order"`
|
||||
WaitTimeout *string `mapstructure:"ip_wait_timeout" cty:"ip_wait_timeout"`
|
||||
|
|
@ -114,7 +115,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"vcenter_server": &hcldec.AttrSpec{Name: "vcenter_server", Type: cty.String, Required: false},
|
||||
"username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false},
|
||||
|
|
@ -144,7 +145,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"video_ram": &hcldec.AttrSpec{Name: "video_ram", Type: cty.Number, Required: false},
|
||||
"vgpu_profile": &hcldec.AttrSpec{Name: "vgpu_profile", Type: cty.String, Required: false},
|
||||
"NestedHV": &hcldec.AttrSpec{Name: "NestedHV", Type: cty.Bool, Required: false},
|
||||
"configuration_parameters": &hcldec.BlockAttrsSpec{TypeName: "configuration_parameters", ElementType: cty.String, Required: false},
|
||||
"firmware": &hcldec.AttrSpec{Name: "firmware", Type: cty.String, Required: false},
|
||||
"configuration_parameters": &hcldec.AttrSpec{Name: "configuration_parameters", Type: cty.Map(cty.String), Required: false},
|
||||
"boot_order": &hcldec.AttrSpec{Name: "boot_order", Type: cty.String, Required: false},
|
||||
"ip_wait_timeout": &hcldec.AttrSpec{Name: "ip_wait_timeout", Type: cty.String, Required: false},
|
||||
"ip_settle_timeout": &hcldec.AttrSpec{Name: "ip_settle_timeout", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ func (*ConfigParamsConfig) FlatMapstructure() interface{ HCL2Spec() map[string]h
|
|||
// The decoded values from this spec will then be applied to a FlatConfigParamsConfig.
|
||||
func (*FlatConfigParamsConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"configuration_parameters": &hcldec.BlockAttrsSpec{TypeName: "configuration_parameters", ElementType: cty.String, Required: false},
|
||||
"configuration_parameters": &hcldec.AttrSpec{Name: "configuration_parameters", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ type HardwareConfig struct {
|
|||
VGPUProfile string `mapstructure:"vgpu_profile"`
|
||||
// Enable nested hardware virtualization for VM. Defaults to `false`.
|
||||
NestedHV bool `mapstructure:"NestedHV"`
|
||||
// Set the Firmware for virtual machine. Supported values: `bios`, `efi`, `efi-secure` or empty string to keep as in template. Defaults to empty string.
|
||||
Firmware string `mapstructure:"firmware"`
|
||||
}
|
||||
|
||||
func (c *HardwareConfig) Prepare() []error {
|
||||
|
|
@ -48,6 +50,10 @@ func (c *HardwareConfig) Prepare() []error {
|
|||
errs = append(errs, fmt.Errorf("'RAM_reservation' and 'RAM_reserve_all' cannot be used together"))
|
||||
}
|
||||
|
||||
if c.Firmware != "" && c.Firmware != "bios" && c.Firmware != "efi" && c.Firmware != "efi-secure" {
|
||||
errs = append(errs, fmt.Errorf("'firmware' must be '', 'bios', 'efi' or 'efi-secure'"))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
|
|
@ -75,6 +81,7 @@ func (s *StepConfigureHardware) Run(_ context.Context, state multistep.StateBag)
|
|||
MemoryHotAddEnabled: s.Config.MemoryHotAddEnabled,
|
||||
VideoRAM: s.Config.VideoRAM,
|
||||
VGPUProfile: s.Config.VGPUProfile,
|
||||
Firmware: s.Config.Firmware,
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ type FlatHardwareConfig struct {
|
|||
VideoRAM *int64 `mapstructure:"video_ram" cty:"video_ram"`
|
||||
VGPUProfile *string `mapstructure:"vgpu_profile" cty:"vgpu_profile"`
|
||||
NestedHV *bool `mapstructure:"NestedHV" cty:"NestedHV"`
|
||||
Firmware *string `mapstructure:"firmware" cty:"firmware"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatHardwareConfig.
|
||||
|
|
@ -47,6 +48,7 @@ func (*FlatHardwareConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"video_ram": &hcldec.AttrSpec{Name: "video_ram", Type: cty.Number, Required: false},
|
||||
"vgpu_profile": &hcldec.AttrSpec{Name: "vgpu_profile", Type: cty.String, Required: false},
|
||||
"NestedHV": &hcldec.AttrSpec{Name: "NestedHV", Type: cty.Bool, Required: false},
|
||||
"firmware": &hcldec.AttrSpec{Name: "firmware", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ type HardwareConfig struct {
|
|||
MemoryHotAddEnabled bool
|
||||
VideoRAM int64
|
||||
VGPUProfile string
|
||||
Firmware string
|
||||
}
|
||||
|
||||
type NIC struct {
|
||||
|
|
@ -71,7 +72,7 @@ type CreateConfig struct {
|
|||
NICs []NIC
|
||||
USBController bool
|
||||
Version uint // example: 10
|
||||
Firmware string // efi or bios
|
||||
Firmware string // efi-secure, efi or bios
|
||||
Storage []Disk
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +109,12 @@ func (d *Driver) CreateVM(config *CreateConfig) (*VirtualMachine, error) {
|
|||
if config.Version != 0 {
|
||||
createSpec.Version = fmt.Sprintf("%s%d", "vmx-", config.Version)
|
||||
}
|
||||
if config.Firmware != "" {
|
||||
if config.Firmware == "efi-secure" {
|
||||
createSpec.Firmware = "efi"
|
||||
createSpec.BootOptions = &types.VirtualMachineBootOptions{
|
||||
EfiSecureBootEnabled: types.NewBool(true),
|
||||
}
|
||||
} else if config.Firmware != "" {
|
||||
createSpec.Firmware = config.Firmware
|
||||
}
|
||||
|
||||
|
|
@ -376,6 +382,15 @@ func (vm *VirtualMachine) Configure(config *HardwareConfig) error {
|
|||
confSpec.DeviceChange = append(confSpec.DeviceChange, spec)
|
||||
}
|
||||
|
||||
if config.Firmware == "efi-secure" || config.Firmware == "efi" {
|
||||
confSpec.Firmware = "efi"
|
||||
confSpec.BootOptions = &types.VirtualMachineBootOptions{
|
||||
EfiSecureBootEnabled: types.NewBool(config.Firmware == "efi-secure"),
|
||||
}
|
||||
} else if config.Firmware != "" {
|
||||
confSpec.Firmware = config.Firmware
|
||||
}
|
||||
|
||||
task, err := vm.vm.Reconfigure(vm.driver.ctx, confSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
|
|
@ -182,7 +182,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"video_ram": &hcldec.AttrSpec{Name: "video_ram", Type: cty.Number, Required: false},
|
||||
"vgpu_profile": &hcldec.AttrSpec{Name: "vgpu_profile", Type: cty.String, Required: false},
|
||||
"NestedHV": &hcldec.AttrSpec{Name: "NestedHV", Type: cty.Bool, Required: false},
|
||||
"configuration_parameters": &hcldec.BlockAttrsSpec{TypeName: "configuration_parameters", ElementType: cty.String, Required: false},
|
||||
"configuration_parameters": &hcldec.AttrSpec{Name: "configuration_parameters", Type: cty.Map(cty.String), Required: false},
|
||||
"iso_checksum": &hcldec.AttrSpec{Name: "iso_checksum", Type: cty.String, Required: false},
|
||||
"iso_checksum_url": &hcldec.AttrSpec{Name: "iso_checksum_url", Type: cty.String, Required: false},
|
||||
"iso_checksum_type": &hcldec.AttrSpec{Name: "iso_checksum_type", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -13,6 +13,22 @@ import (
|
|||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// Defines a Network Adapter
|
||||
//
|
||||
// Example that creates two network adapters:
|
||||
//
|
||||
// ```json
|
||||
// "network_adapters": [
|
||||
// {
|
||||
// "network": "VM Network",
|
||||
// "network_card": "vmxnet3"
|
||||
// },
|
||||
// {
|
||||
// "network": "OtherNetwork",
|
||||
// "network_card": "vmxnet3"
|
||||
// }
|
||||
// ],
|
||||
// ```
|
||||
type NIC struct {
|
||||
// Set network VM will be connected to.
|
||||
Network string `mapstructure:"network"`
|
||||
|
|
@ -24,8 +40,23 @@ type NIC struct {
|
|||
Passthrough *bool `mapstructure:"passthrough"`
|
||||
}
|
||||
|
||||
// Defines the disk storage for a VM.
|
||||
//
|
||||
// Example that will create a 15GB and a 20GB disk on the VM. The second disk will be thin provisioned:
|
||||
//
|
||||
// ```json
|
||||
// "storage": [
|
||||
// {
|
||||
// "disk_size": 15000,
|
||||
// },
|
||||
// {
|
||||
// "disk_size": 20000,
|
||||
// "disk_thin_provisioned": true
|
||||
// }
|
||||
// ],
|
||||
// ```
|
||||
type DiskConfig struct {
|
||||
// Set the size of the disk
|
||||
// The size of the disk in MB.
|
||||
DiskSize int64 `mapstructure:"disk_size" required:"true"`
|
||||
// Enable VMDK thin provisioning for VM. Defaults to `false`.
|
||||
DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"`
|
||||
|
|
@ -43,7 +74,7 @@ type CreateConfig struct {
|
|||
// here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
||||
// for a full list of possible values.
|
||||
GuestOSType string `mapstructure:"guest_os_type"`
|
||||
// Set the Firmware at machine creation. Example `efi`. Defaults to `bios`.
|
||||
// Set the Firmware at machine creation. Supported values: `bios`, `efi` or `efi-secure`. Defaults to `bios`.
|
||||
Firmware string `mapstructure:"firmware"`
|
||||
// Set VM disk controller type. Example `pvscsi`.
|
||||
DiskControllerType string `mapstructure:"disk_controller_type"`
|
||||
|
|
@ -84,8 +115,8 @@ func (c *CreateConfig) Prepare() []error {
|
|||
c.GuestOSType = "otherGuest"
|
||||
}
|
||||
|
||||
if c.Firmware != "" && c.Firmware != "bios" && c.Firmware != "efi" {
|
||||
errs = append(errs, fmt.Errorf("'firmware' must be 'bios' or 'efi'"))
|
||||
if c.Firmware != "" && c.Firmware != "bios" && c.Firmware != "efi" && c.Firmware != "efi-secure" {
|
||||
errs = append(errs, fmt.Errorf("'firmware' must be 'bios', 'efi' or 'efi-secure'"))
|
||||
}
|
||||
|
||||
return errs
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"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_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(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},
|
||||
|
|
@ -163,18 +163,18 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"disk_type": &hcldec.AttrSpec{Name: "disk_type", Type: cty.String, Required: false},
|
||||
"image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false},
|
||||
"image_family": &hcldec.AttrSpec{Name: "image_family", Type: cty.String, Required: false},
|
||||
"image_labels": &hcldec.BlockAttrsSpec{TypeName: "image_labels", ElementType: cty.String, Required: false},
|
||||
"image_labels": &hcldec.AttrSpec{Name: "image_labels", Type: cty.Map(cty.String), Required: false},
|
||||
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
|
||||
"image_product_ids": &hcldec.AttrSpec{Name: "image_product_ids", Type: cty.List(cty.String), Required: false},
|
||||
"instance_cores": &hcldec.AttrSpec{Name: "instance_cores", Type: cty.Number, Required: false},
|
||||
"instance_gpus": &hcldec.AttrSpec{Name: "instance_gpus", Type: cty.Number, Required: false},
|
||||
"instance_mem_gb": &hcldec.AttrSpec{Name: "instance_mem_gb", Type: cty.Number, Required: false},
|
||||
"instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false},
|
||||
"labels": &hcldec.BlockAttrsSpec{TypeName: "labels", ElementType: cty.String, Required: false},
|
||||
"labels": &hcldec.AttrSpec{Name: "labels", Type: cty.Map(cty.String), Required: false},
|
||||
"platform_id": &hcldec.AttrSpec{Name: "platform_id", Type: cty.String, Required: false},
|
||||
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
|
||||
"metadata": &hcldec.BlockAttrsSpec{TypeName: "metadata", ElementType: cty.String, Required: false},
|
||||
"metadata_from_file": &hcldec.BlockAttrsSpec{TypeName: "metadata_from_file", ElementType: cty.String, Required: false},
|
||||
"metadata": &hcldec.AttrSpec{Name: "metadata", Type: cty.Map(cty.String), Required: false},
|
||||
"metadata_from_file": &hcldec.AttrSpec{Name: "metadata_from_file", Type: cty.Map(cty.String), Required: false},
|
||||
"preemptible": &hcldec.AttrSpec{Name: "preemptible", Type: cty.Bool, Required: false},
|
||||
"serial_log_file": &hcldec.AttrSpec{Name: "serial_log_file", Type: cty.String, Required: false},
|
||||
"source_image_family": &hcldec.AttrSpec{Name: "source_image_family", Type: cty.String, Required: false},
|
||||
|
|
|
|||
|
|
@ -260,10 +260,9 @@ func goFieldToCtyType(accessor string, fieldType types.Type) (interface{}, cty.T
|
|||
Required: false,
|
||||
}, ctyType
|
||||
case *types.Map:
|
||||
return &hcldec.BlockAttrsSpec{
|
||||
TypeName: accessor,
|
||||
ElementType: cty.String, // for now everything can be simplified to a map[string]string
|
||||
Required: false,
|
||||
return &hcldec.AttrSpec{
|
||||
Name: accessor,
|
||||
Type: cty.Map(cty.String), // for now everything can be simplified to a map[string]string
|
||||
}, cty.Map(cty.String)
|
||||
case *types.Named:
|
||||
// Named is the relative type when of a field with a struct.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package command
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -12,12 +13,14 @@ import (
|
|||
"github.com/hashicorp/packer/builder/file"
|
||||
"github.com/hashicorp/packer/builder/null"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/post-processor/manifest"
|
||||
shell_local_pp "github.com/hashicorp/packer/post-processor/shell-local"
|
||||
filep "github.com/hashicorp/packer/provisioner/file"
|
||||
"github.com/hashicorp/packer/provisioner/shell"
|
||||
shell_local "github.com/hashicorp/packer/provisioner/shell-local"
|
||||
)
|
||||
|
||||
func TestBuild_VarArgs(t *testing.T) {
|
||||
func TestBuild(t *testing.T) {
|
||||
tc := []struct {
|
||||
name string
|
||||
args []string
|
||||
|
|
@ -25,7 +28,7 @@ func TestBuild_VarArgs(t *testing.T) {
|
|||
fileCheck
|
||||
}{
|
||||
{
|
||||
name: "json - json varfile sets an apple env var",
|
||||
name: "var-args: json - json varfile sets an apple env var",
|
||||
args: []string{
|
||||
"-var-file=" + filepath.Join(testFixture("var-arg"), "apple.json"),
|
||||
filepath.Join(testFixture("var-arg"), "fruit_builder.json"),
|
||||
|
|
@ -43,7 +46,7 @@ func TestBuild_VarArgs(t *testing.T) {
|
|||
fileCheck: fileCheck{expected: []string{"banana.txt"}},
|
||||
},
|
||||
{
|
||||
name: "json - arg sets a pear env var",
|
||||
name: "var-args: json - arg sets a pear env var",
|
||||
args: []string{
|
||||
"-var=fruit=pear",
|
||||
filepath.Join(testFixture("var-arg"), "fruit_builder.json"),
|
||||
|
|
@ -52,7 +55,7 @@ func TestBuild_VarArgs(t *testing.T) {
|
|||
},
|
||||
|
||||
{
|
||||
name: "json - inexistent var file errs",
|
||||
name: "var-args: json - inexistent var file errs",
|
||||
args: []string{
|
||||
"-var-file=" + filepath.Join(testFixture("var-arg"), "potato.json"),
|
||||
filepath.Join(testFixture("var-arg"), "fruit_builder.json"),
|
||||
|
|
@ -62,7 +65,7 @@ func TestBuild_VarArgs(t *testing.T) {
|
|||
},
|
||||
|
||||
{
|
||||
name: "hcl - inexistent json var file errs",
|
||||
name: "var-args: hcl - inexistent json var file errs",
|
||||
args: []string{
|
||||
"-var-file=" + filepath.Join(testFixture("var-arg"), "potato.json"),
|
||||
testFixture("var-arg"),
|
||||
|
|
@ -72,7 +75,7 @@ func TestBuild_VarArgs(t *testing.T) {
|
|||
},
|
||||
|
||||
{
|
||||
name: "hcl - inexistent hcl var file errs",
|
||||
name: "var-args: hcl - inexistent hcl var file errs",
|
||||
args: []string{
|
||||
"-var-file=" + filepath.Join(testFixture("var-arg"), "potato.hcl"),
|
||||
testFixture("var-arg"),
|
||||
|
|
@ -82,7 +85,7 @@ func TestBuild_VarArgs(t *testing.T) {
|
|||
},
|
||||
|
||||
{
|
||||
name: "hcl - auto varfile sets a chocolate env var",
|
||||
name: "var-args: hcl - auto varfile sets a chocolate env var",
|
||||
args: []string{
|
||||
testFixture("var-arg"),
|
||||
},
|
||||
|
|
@ -90,7 +93,7 @@ func TestBuild_VarArgs(t *testing.T) {
|
|||
},
|
||||
|
||||
{
|
||||
name: "hcl - hcl varfile sets a apple env var",
|
||||
name: "var-args: hcl - hcl varfile sets a apple env var",
|
||||
args: []string{
|
||||
"-var-file=" + filepath.Join(testFixture("var-arg"), "apple.hcl"),
|
||||
testFixture("var-arg"),
|
||||
|
|
@ -99,7 +102,7 @@ func TestBuild_VarArgs(t *testing.T) {
|
|||
},
|
||||
|
||||
{
|
||||
name: "hcl - json varfile sets a apple env var",
|
||||
name: "var-args: hcl - json varfile sets a apple env var",
|
||||
args: []string{
|
||||
"-var-file=" + filepath.Join(testFixture("var-arg"), "apple.json"),
|
||||
testFixture("var-arg"),
|
||||
|
|
@ -108,19 +111,108 @@ func TestBuild_VarArgs(t *testing.T) {
|
|||
},
|
||||
|
||||
{
|
||||
name: "hcl - arg sets a tomato env var",
|
||||
name: "var-args: hcl - arg sets a tomato env var",
|
||||
args: []string{
|
||||
"-var=fruit=tomato",
|
||||
testFixture("var-arg"),
|
||||
},
|
||||
fileCheck: fileCheck{expected: []string{"tomato.txt"}},
|
||||
},
|
||||
|
||||
{
|
||||
name: "build name: HCL",
|
||||
args: []string{
|
||||
"-parallel-builds=1", // to ensure order is kept
|
||||
testFixture("build-name-and-type"),
|
||||
},
|
||||
fileCheck: fileCheck{
|
||||
expectedContent: map[string]string{
|
||||
"manifest.json": `{
|
||||
"builds": [
|
||||
{
|
||||
"name": "test",
|
||||
"builder_type": "null",
|
||||
"files": null,
|
||||
"artifact_id": "Null",
|
||||
"packer_run_uuid": "",
|
||||
"custom_data": null
|
||||
},
|
||||
{
|
||||
"name": "potato",
|
||||
"builder_type": "null",
|
||||
"files": null,
|
||||
"artifact_id": "Null",
|
||||
"packer_run_uuid": "",
|
||||
"custom_data": null
|
||||
}
|
||||
],
|
||||
"last_run_uuid": ""
|
||||
}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "build name: JSON except potato",
|
||||
args: []string{
|
||||
"-except=potato",
|
||||
"-parallel-builds=1", // to ensure order is kept
|
||||
filepath.Join(testFixture("build-name-and-type"), "all.json"),
|
||||
},
|
||||
fileCheck: fileCheck{
|
||||
expected: []string{
|
||||
"null.test.txt",
|
||||
"null.potato.txt",
|
||||
},
|
||||
expectedContent: map[string]string{
|
||||
"manifest.json": `{
|
||||
"builds": [
|
||||
{
|
||||
"name": "test",
|
||||
"builder_type": "null",
|
||||
"files": null,
|
||||
"artifact_id": "Null",
|
||||
"packer_run_uuid": "",
|
||||
"custom_data": null
|
||||
}
|
||||
],
|
||||
"last_run_uuid": ""
|
||||
}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "build name: JSON only potato",
|
||||
args: []string{
|
||||
"-only=potato",
|
||||
"-parallel-builds=1", // to ensure order is kept
|
||||
filepath.Join(testFixture("build-name-and-type"), "all.json"),
|
||||
},
|
||||
fileCheck: fileCheck{
|
||||
expectedContent: map[string]string{
|
||||
"manifest.json": `{
|
||||
"builds": [
|
||||
{
|
||||
"name": "potato",
|
||||
"builder_type": "null",
|
||||
"files": null,
|
||||
"artifact_id": "Null",
|
||||
"packer_run_uuid": "",
|
||||
"custom_data": null
|
||||
}
|
||||
],
|
||||
"last_run_uuid": ""
|
||||
}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tc {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
defer tt.cleanup(t)
|
||||
run(t, tt.args, tt.expectedCode)
|
||||
defer cleanup()
|
||||
tt.fileCheck.verify(t)
|
||||
})
|
||||
}
|
||||
|
|
@ -340,10 +432,28 @@ func run(t *testing.T, args []string, expectedCode int) {
|
|||
|
||||
type fileCheck struct {
|
||||
expected, notExpected []string
|
||||
expectedContent map[string]string
|
||||
}
|
||||
|
||||
func (fc fileCheck) cleanup(t *testing.T) {
|
||||
for _, file := range fc.expectedFiles() {
|
||||
t.Logf("removing %v", file)
|
||||
if err := os.Remove(file); err != nil {
|
||||
t.Errorf("failed to remove file %s: %v", file, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (fc fileCheck) expectedFiles() []string {
|
||||
expected := fc.expected
|
||||
for file := range fc.expectedContent {
|
||||
expected = append(expected, file)
|
||||
}
|
||||
return expected
|
||||
}
|
||||
|
||||
func (fc fileCheck) verify(t *testing.T) {
|
||||
for _, f := range fc.expected {
|
||||
for _, f := range fc.expectedFiles() {
|
||||
if !fileExists(f) {
|
||||
t.Errorf("Expected to find %s", f)
|
||||
}
|
||||
|
|
@ -353,6 +463,15 @@ func (fc fileCheck) verify(t *testing.T) {
|
|||
t.Errorf("Expected to not find %s", f)
|
||||
}
|
||||
}
|
||||
for file, expectedContent := range fc.expectedContent {
|
||||
content, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
t.Fatalf("ioutil.ReadFile: %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(expectedContent, string(content)); diff != "" {
|
||||
t.Errorf("content of %s differs: %s", file, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fileExists returns true if the filename is found
|
||||
|
|
@ -374,9 +493,11 @@ func testCoreConfigBuilder(t *testing.T) *packer.CoreConfig {
|
|||
ProvisionerStore: packer.MapOfProvisioner{
|
||||
"shell-local": func() (packer.Provisioner, error) { return &shell_local.Provisioner{}, nil },
|
||||
"shell": func() (packer.Provisioner, error) { return &shell.Provisioner{}, nil },
|
||||
"file": func() (packer.Provisioner, error) { return &filep.Provisioner{}, nil },
|
||||
},
|
||||
PostProcessorStore: packer.MapOfPostProcessor{
|
||||
"shell-local": func() (packer.PostProcessor, error) { return &shell_local_pp.PostProcessor{}, nil },
|
||||
"manifest": func() (packer.PostProcessor, error) { return &manifest.PostProcessor{}, nil },
|
||||
},
|
||||
}
|
||||
return &packer.CoreConfig{
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/hashicorp/packer/helper/wrappedreadline"
|
||||
"github.com/hashicorp/packer/helper/wrappedstreams"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
|
|
@ -115,7 +116,7 @@ func (*ConsoleCommand) AutocompleteFlags() complete.Flags {
|
|||
|
||||
func (c *ConsoleCommand) modePiped(session *REPLSession) int {
|
||||
var lastResult string
|
||||
scanner := bufio.NewScanner(wrappedreadline.Stdin())
|
||||
scanner := bufio.NewScanner(wrappedstreams.Stdin())
|
||||
for scanner.Scan() {
|
||||
result, err := session.Handle(strings.TrimSpace(scanner.Text()))
|
||||
if err != nil {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue