Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b3927f395d |
+60
-29
@@ -8,7 +8,6 @@ executors:
|
||||
golang:
|
||||
docker:
|
||||
- image: circleci/golang:1.13
|
||||
resource_class: medium+
|
||||
darwin:
|
||||
macos:
|
||||
xcode: "9.0"
|
||||
@@ -81,7 +80,7 @@ jobs:
|
||||
file: coverage.txt
|
||||
check-lint:
|
||||
executor: golang
|
||||
resource_class: xlarge
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
- run: git fetch --all
|
||||
@@ -151,6 +150,15 @@ jobs:
|
||||
- store_artifacts:
|
||||
path: ./pkg/
|
||||
destination: /
|
||||
publish-github-tag-release:
|
||||
docker:
|
||||
- image: cibuilds/github:0.10
|
||||
working_directory: /go/src/github.com/hashicorp/packer
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: |
|
||||
ghr -prerelease -t ${GITHUB_TOKEN_AZR} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${CIRCLE_TAG} ./pkg/
|
||||
build-website-docker-image:
|
||||
docker:
|
||||
- image: circleci/buildpack-deps
|
||||
@@ -172,21 +180,6 @@ jobs:
|
||||
docker login -u $WEBSITE_DOCKER_USER -p $WEBSITE_DOCKER_PASS
|
||||
docker push hashicorp/packer-website
|
||||
fi
|
||||
algolia-index:
|
||||
docker:
|
||||
- image: node:12
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Push content to Algolia Index
|
||||
command: |
|
||||
if [ "$CIRCLE_REPOSITORY_URL" != "git@github.com:hashicorp/packer.git" ]; then
|
||||
echo "Not Packer OSS Repo, not indexing Algolia"
|
||||
exit 0
|
||||
fi
|
||||
cd website/
|
||||
npm install
|
||||
node scripts/index_search_content.js
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@@ -203,12 +196,42 @@ workflows:
|
||||
- check-generate
|
||||
build_packer_binaries:
|
||||
jobs:
|
||||
- build_linux
|
||||
- build_darwin
|
||||
- build_windows
|
||||
- build_freebsd
|
||||
- build_openbsd
|
||||
- build_solaris
|
||||
- build_linux:
|
||||
requires:
|
||||
- test
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- build_darwin:
|
||||
requires:
|
||||
- test
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- build_windows:
|
||||
requires:
|
||||
- test
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- build_freebsd:
|
||||
requires:
|
||||
- test
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- build_openbsd:
|
||||
requires:
|
||||
- test
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- build_solaris:
|
||||
requires:
|
||||
- test
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- store_artifacts:
|
||||
requires:
|
||||
- build_linux
|
||||
@@ -217,15 +240,23 @@ workflows:
|
||||
- build_freebsd
|
||||
- build_openbsd
|
||||
- build_solaris
|
||||
website:
|
||||
- publish-github-tag-release:
|
||||
requires:
|
||||
- build_linux
|
||||
- build_darwin
|
||||
- build_windows
|
||||
- build_freebsd
|
||||
- build_openbsd
|
||||
- build_solaris
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: nightly
|
||||
build_website_docker_image:
|
||||
jobs:
|
||||
- build-website-docker-image:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- algolia-index:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- stable-website
|
||||
|
||||
+4
-2
@@ -10,8 +10,10 @@ comment:
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project: off
|
||||
patch: off
|
||||
project:
|
||||
default:
|
||||
target: auto
|
||||
threshold: "0.5%"
|
||||
|
||||
ignore: # ignore hcl2spec generated code for coverage
|
||||
- "**/*.hcl2spec.go"
|
||||
+29
-40
@@ -46,18 +46,7 @@ can quickly merge or address your contributions.
|
||||
referenced in the commit message so that the code that fixes it is clearly
|
||||
linked.
|
||||
|
||||
5. Sometimes, if you have a specialized environment or use case, the maintainers
|
||||
may ask for your help testing the patch. You are able to download an
|
||||
experimental binary of Packer containing the Pull Request's patch via from
|
||||
the Pull Request page on github. You can do this by scrolling to the
|
||||
"checks" section on github, and clicking "details" on the
|
||||
"store_artifacts" check. This will take you to Packer's Circle CI page for
|
||||
the build, and you will be able to click a tab named "Artifacts" which will
|
||||
contain zipped Packer binaries for each major OS architecture.
|
||||
|
||||
6. The issue is closed.
|
||||
|
||||
|
||||
5. The issue is closed.
|
||||
|
||||
## Setting up Go
|
||||
|
||||
@@ -347,11 +336,11 @@ may incur costs for real money. In the presence of a bug, it is possible that
|
||||
resources may be left behind, which can cost money even though you were not
|
||||
using them. We recommend running tests in an account used only for that purpose
|
||||
so it is easy to see if there are any dangling resources, and so production
|
||||
resources are not accidentally destroyed or overwritten during testing.
|
||||
Also, these typically require an API key (AWS, GCE), or additional software
|
||||
resources are not accidentally destroyed or overwritten during testing.
|
||||
Also, these typically require an API key (AWS, GCE), or additional software
|
||||
to be installed on your computer (VirtualBox, VMware).
|
||||
|
||||
To run the Provisioners Acceptance Tests you should use both **ACC_TEST_BUILDERS** and **ACC_TEST_PROVISIONERS** variables to
|
||||
To run the Provisioners Acceptance Tests you should use both **ACC_TEST_BUILDERS** and **ACC_TEST_PROVISIONERS** variables to
|
||||
tell which provisioner and builder the test should be run against.
|
||||
|
||||
Examples of usage:
|
||||
@@ -377,14 +366,14 @@ Examples of usage:
|
||||
ACC_TEST_BUILDERS=all ACC_TEST_PROVISIONERS=all make provisioners-acctest
|
||||
```
|
||||
|
||||
Both **ACC_TEST_BUILDERS** and **ACC_TEST_PROVISIONERS** allows defining a list of builders and provisioners separated by comma
|
||||
(e.g. `ACC_TEST_BUILDERS=amazon-ebs,virtualbox-iso`)
|
||||
Both **ACC_TEST_BUILDERS** and **ACC_TEST_PROVISIONERS** allows defining a list of builders and provisioners separated by comma
|
||||
(e.g. `ACC_TEST_BUILDERS=amazon-ebs,virtualbox-iso`)
|
||||
|
||||
|
||||
#### Writing Provisioner Acceptance Tests
|
||||
|
||||
Packer has an already implemented structure that will run the provisioner against builders and you can find it in `helper/tests/acc/provisioners.go`.
|
||||
All provisioners should use this structure in their acceptance tests.
|
||||
All provisioners should use this structure in their acceptance tests.
|
||||
|
||||
To start writing a new provisioner acceptance test, you should add a test file named as `provisioner_acc_test.go` in the provisioner folder
|
||||
and the package should be `<provisioner>_test`. This file should have a struct that will implement the ProvisionerAcceptance interface.
|
||||
@@ -401,7 +390,7 @@ type ProvisionerAcceptance interface {
|
||||
|
||||
- **GetName()** should return the provisioner type. For example for the Shell provisioner the method returns "shell".
|
||||
|
||||
- **GetConfig()** should read a text file with the json configuration block for the provisioner and any other necessary provisioner.
|
||||
- **GetConfig()** should read a text file with the json configuration block for the provisioner and any other necessary provisioner.
|
||||
For the Shell one the file contains:
|
||||
|
||||
```
|
||||
@@ -418,11 +407,11 @@ For the Shell one the file contains:
|
||||
"direction": "download"
|
||||
}
|
||||
```
|
||||
The file should be placed under the `test-fixtures` folder.
|
||||
In this case, it's necessary to use the File provisioner to validate if the Shell provisioner test is successful or not.
|
||||
The file should be placed under the `test-fixtures` folder.
|
||||
In this case, it's necessary to use the File provisioner to validate if the Shell provisioner test is successful or not.
|
||||
This config should be returned as string that will be later merged with the builder config into a full template.
|
||||
|
||||
- **GetProvisionerStore()** this returns the provisioner store where we declare the available provisioners for running the build.
|
||||
- **GetProvisionerStore()** this returns the provisioner store where we declare the available provisioners for running the build.
|
||||
For the Shell provisioners this is:
|
||||
```go
|
||||
func (s *ShellProvisionerAccTest) GetProvisionerStore() packer.MapOfProvisioner {
|
||||
@@ -437,7 +426,7 @@ For the Shell provisioners this is:
|
||||
specific builder or/and specific OS.
|
||||
|
||||
- **RunTest(c \*command.BuildCommand, args []string)** it will actually run the build and return any error if it fails the validations.
|
||||
For the Shell provisioner this is:
|
||||
For the Shell provisioner this is:
|
||||
```go
|
||||
func (s *ShellProvisionerAccTest) RunTest(c *command.BuildCommand, args []string) error {
|
||||
// Provisioner specific setup
|
||||
@@ -445,11 +434,11 @@ For the Shell provisioner this is:
|
||||
if UUID == "" {
|
||||
UUID, _ = uuid.GenerateUUID()
|
||||
os.Setenv("PACKER_RUN_UUID", UUID)
|
||||
}
|
||||
}
|
||||
file := "provisioner.shell." + UUID + ".txt"
|
||||
defer testshelper.CleanupFiles(file)
|
||||
|
||||
// Run build
|
||||
|
||||
// Run build
|
||||
// All provisioner acc tests should contain this code and validation
|
||||
if code := c.Run(args); code != 0 {
|
||||
ui := c.Meta.Ui.(*packer.BasicUi)
|
||||
@@ -460,31 +449,31 @@ For the Shell provisioner this is:
|
||||
out.String(),
|
||||
err.String())
|
||||
}
|
||||
|
||||
|
||||
// Any other extra specific validation
|
||||
if !testshelper.FileExists(file) {
|
||||
return fmt.Errorf("Expected to find %s", file)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
After writing the struct and implementing the interface, now is time to write the test that will run all
|
||||
of this code you wrote. Your test should be like:
|
||||
of this code you wrote. Your test should be like:
|
||||
|
||||
```go
|
||||
func TestShellProvisioner(t *testing.T) {
|
||||
acc.TestProvisionersPreCheck("shell", t)
|
||||
acc.TestProvisionersAgainstBuilders(new(ShellProvisionerAccTest), t)
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
If the environment variable **ACC_TEST_PROVISIONERS** is set as `all` or contains the provisioner type, then the test should run, otherwise the test should skip.
|
||||
In case of running it, you'll need to call the helper function `acc.TestProvisionersAgainstBuilders` passing a pointer to the test struct created above and the test testing pointer.
|
||||
In case of running it, you'll need to call the helper function `acc.TestProvisionersAgainstBuilders` passing a pointer to the test struct created above and the test testing pointer.
|
||||
|
||||
The method `TestProvisionersAgainstBuilders` will run the provisioner against all available and compatible builders. An available builder
|
||||
is the one that has the necessary code for running this type of test. In case the builder you want to run against is not available for testing, you can write it following the next steps.
|
||||
is the one that has the necessary code for running this type of test. In case the builder you want to run against is not available for testing, you can write it following the next steps.
|
||||
|
||||
To add a new builder to the available builders for provisioners acc testing, you'll need to create a new folder under the builder folder
|
||||
called `acceptance` and inside you create the `builder_acceptance.go` file and the package should be `<builder>_acc`. Like the provisioners, you'll need to create a struct that will
|
||||
@@ -496,7 +485,7 @@ type BuilderAcceptance interface {
|
||||
CleanUp() error
|
||||
}
|
||||
```
|
||||
- **GetConfigs()** should read a text file with the json configuration block for the builder and return a map of configs by OS type.
|
||||
- **GetConfigs()** should read a text file with the json configuration block for the builder and return a map of configs by OS type.
|
||||
For the Amazon EBS builder the file contains:
|
||||
```
|
||||
{
|
||||
@@ -512,11 +501,11 @@ For the Amazon EBS builder the file contains:
|
||||
}
|
||||
}
|
||||
```
|
||||
The file should be placed under the `test-fixtures` folder.
|
||||
The file should be placed under the `test-fixtures` folder.
|
||||
In case you need to make references to another file, you'll need to add the relative path to provisioners folder like:
|
||||
`../../builder/amazon/ebs/acceptance/test-fixtures/file.txt`.
|
||||
`../../builder/amazon/ebs/acceptance/test-fixtures/file.txt`.
|
||||
|
||||
- **GetBuilderStore()** this returns the builder store where we declare the available builders for running the build.
|
||||
- **GetBuilderStore()** this returns the builder store where we declare the available builders for running the build.
|
||||
For the Amazon EBS builder this is:
|
||||
```go
|
||||
func (s *AmazonEBSAccTest) GetBuilderStore() packer.MapOfBuilder {
|
||||
@@ -525,7 +514,7 @@ For the Amazon EBS builder this is:
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
- **CleanUp()** cleans any resource created by the builder whether local or remote.
|
||||
|
||||
Once you created the builder necessary code, the last step is adding it to the `BuildersAccTest` map in `helper/tests/acc/provisioners.go`.
|
||||
@@ -537,7 +526,7 @@ var BuildersAccTest = map[string]BuilderAcceptance{
|
||||
}
|
||||
```
|
||||
|
||||
Once you finish the steps, you should be ready to run your new provisioner acceptance test.
|
||||
Once you finish the steps, you should be ready to run your new provisioner acceptance test.
|
||||
|
||||
#### Debugging Plugins
|
||||
|
||||
|
||||
@@ -9,23 +9,10 @@ reaction feature
|
||||
(https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/)
|
||||
to add upvotes to pre-existing requests.
|
||||
|
||||
#### Community Note
|
||||
|
||||
Please vote on this issue by adding a 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original issue to help the community and maintainers prioritize this request.
|
||||
Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request.
|
||||
If you are interested in working on this issue or have submitted a pull request, please leave a comment.
|
||||
|
||||
#### Description
|
||||
#### Feature Description
|
||||
|
||||
A written overview of the feature.
|
||||
|
||||
#### Use Case(s)
|
||||
|
||||
Any relevant use-cases that you see.
|
||||
|
||||
#### Potential configuration
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
#### Potential References
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
name: Milestone Labeler
|
||||
on:
|
||||
issues:
|
||||
types: [milestoned]
|
||||
jobs:
|
||||
apply_labels:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Add track-internal
|
||||
uses: andymckay/labeler@1.0.2
|
||||
with:
|
||||
repo-token: ${{ secrets.Github_Token }}
|
||||
add-labels: "track-internal"
|
||||
+25
-346
@@ -1,345 +1,32 @@
|
||||
## 1.6.1 (July 30, 2020)
|
||||
## 1.5.6 (Upcoming)
|
||||
|
||||
### BACKWARDS INCOMPATABILITIES:
|
||||
|
||||
* HCL: builder/vsphere: Add option to add a xhci/usb3 controller; changes
|
||||
controller value to an array of strings. [GH-9574]
|
||||
* HCL: New HCL-only `post-processors` block to run chained post-processors
|
||||
after a build [GH-9638]. Before this, defining multiple `post-processor`
|
||||
blocks after provisioning steps would run them sequentially, now doing this
|
||||
makes them start from the build artifact. To queue post-processors you now
|
||||
have to define them in a `post-processors` block. [GH-9638]
|
||||
* post-processor/vSphere: We have fixed a bug in the ovftool URL encoding. This
|
||||
may mean that you have performed an encoding workaround that is no longer
|
||||
necessary. [GH-9589]
|
||||
|
||||
### FEATURES:
|
||||
* **New post-processor** Yandex Import [GH-9553]
|
||||
**New Builder** azure-dtl allows creation of devtestlabs images in Azure. [GH-8987]
|
||||
|
||||
### IMPROVEMENTS:
|
||||
* builder/amazon-ebs: Wrap CreateImage call in a retry to account for eventual
|
||||
consistency [GH-9579]
|
||||
* builder/azure: Disable SSH password authentication unless password is
|
||||
explicitly specified. [GH-9603]
|
||||
* builder/docker: Add options for --cap-add, --cap-drop, --tmpfs, --device
|
||||
[GH-9565]
|
||||
* builder/file: Create parent directories of target file, if they don't exist.
|
||||
[GH-9452]
|
||||
* builder/googlecompute: Add `wrap_startup_script` configuration option to
|
||||
allow the disabling of Packer's startup script wrapper [GH-9505]
|
||||
* builder/googlecompute: Add support for oslogin via the `use_os_login`
|
||||
configuration option [GH-9339]
|
||||
* builder/googlecompute: Make IAP tunnel timeout configurable. [GH-9545]
|
||||
* builder/googlecompute: Support using WinRM over an IAP tunnel [GH-9610]
|
||||
* builder/hyper-v: Include secure boot template in box.xml [GH-9552]
|
||||
* builder/hyperone: Add support for custom username in vm creation. [GH-9497]
|
||||
* builder/hyperone: Skip chroot device discovery. [GH-9489]
|
||||
* builder/openstack: Bump gophercloud to latest version [GH-9573]
|
||||
* builder/proxmox: Add option to disable KVM hardware virtualization in Proxmox
|
||||
builder [GH-9587]
|
||||
* builder/proxmox: Add support for multiple NIC packet queues [GH-9597]
|
||||
* builder/proxmox: Enable Proxmox builder to toggle the firewall parameter for
|
||||
network interfaces. [GH-9487]
|
||||
* builder/proxmox: Update Proxmox storagePoolTypes [GH-9418]
|
||||
* builder/qemu: Add 'cdrom_interface' option to QEMU builder [GH-9483]
|
||||
* builder/tencentcloud: Add `source_image_name` to support getting source image
|
||||
by name [GH-9619]
|
||||
* builder/tencentcloud: Update cvm root disk type to `CLOUD_PREMIUM` [GH-9663]
|
||||
* builder/ucloud: New access config options and run config options. [GH-9466]
|
||||
* builder/vsphere-clone: Add `boot_command` support to vsphere-clone builder,
|
||||
including support for starting an HTTP server
|
||||
* builder/vsphere-clone: Add `vapp` configuration option [GH-9507]
|
||||
* builder/vsphere: Add ability to define multiple disk controllers [GH-9519]
|
||||
* builder/vsphere: Add `boot_command` support to vsphere-clone builder. [GH-9397]
|
||||
* builder/vsphere: Add `content_library_destination` to import VM template to a
|
||||
Content Library [GH-9551]
|
||||
* builder/vsphere: Add `force_bios_setup` configuration option [GH-9563]
|
||||
* builder/vsphere: Add option to add a xhci/usb3 controller [GH-9574]
|
||||
* builder/vsphere: Create vm output folders if they don't exist [GH-9402]
|
||||
* builder/vsphere: Fix file size descriptor when exporting OFV [GH-9568]
|
||||
* builder/vsphere: Look at all available IPs in the waiting for IP loop.
|
||||
[GH-9450]
|
||||
* builder/vsphere: Match network to host when multiple networks are found
|
||||
[GH-9556]
|
||||
* builder/vsphere: Update vsphere `boot_command` to bring it in line with other
|
||||
builders' boot_command functionality. [GH-9406]
|
||||
* builder/vsphere: Use datacenter inventory path for find folder [GH-9390]
|
||||
* builder/vsphere: Use value from "ip_wait_address" option to determine the
|
||||
default for the http server IP [GH-9441]
|
||||
* builder/yandex: Allow set `min_disk_size` for an image.
|
||||
* builder/yandex: Support authentication by Service Account on instance
|
||||
[GH-9383]
|
||||
* builder/yandex: yandex: Add new property `min_disk_size` of built image
|
||||
[GH-9594]
|
||||
* communicator/ssh: Add support for OpenSSH certificate signing [GH-9521]
|
||||
* communicator/ssh: Allow users to provide a list of ciphers that they want
|
||||
Packer to support. [GH-9453]
|
||||
* core/hcl2: Add possibility to name singular build.source blocks to
|
||||
differentiate their output and to filter on them [GH-9490]
|
||||
* core/hcl2: Add the "inspect" command for hcl2 configs. [GH-9468]
|
||||
* core/hcl2: HCL configs now respect only/except using build names instead of
|
||||
types. [GH-9454]
|
||||
* core/hcl: Allow use of `keep_input_artifact` in post processors. [GH-9477]
|
||||
* core/hcl: Share build info with Provisioner and Post-Processor via HCL2
|
||||
variables [GH-9444] [GH-9534] [GH-9622]
|
||||
* core: Add on-error flag option to run error-cleanup-provisioner [GH-9429]
|
||||
* core: communicator/ssh: Add new `ssh_key_exchange_algorithms` option to
|
||||
supply custom key exchange algorithms in SSH client [GH-9634]
|
||||
* core: refactor initialization out from Packer core to allow `validate
|
||||
--syntax-only` to no error when a variable is not set [GH-9627]
|
||||
* hcl2: Handle uint64 buildvars [GH-9585]
|
||||
* post-processor/yandex-export: Allow users to utilize generated variables in
|
||||
templating. [GH-9555]
|
||||
* post-processor/yandex-export: Support Authentication by Service Account Key
|
||||
file [GH-9379]
|
||||
* post-processor/yandex-import: Support creating an Image based on another one
|
||||
[GH-9614]
|
||||
* post-processor/yandex-import: Support using URL from yandex-export [GH-9601]
|
||||
* provisioner/ansible: Add template option for templating the inventory file
|
||||
lines [GH-9438]
|
||||
|
||||
### BUG FIXES:
|
||||
* builder/amazon: Change "Resource" field in
|
||||
`temporary_iam_instance_profile_policy_document` to be an array of strings,
|
||||
not just a single string. [GH-9509]
|
||||
* builder/amazon: HCL2: Add singular `run_volume_tag` block to ebs & ebssurrogate
|
||||
builders. [GH-9457]
|
||||
* builder/amazon: Retry fetching block device mappings if empty. [GH-9480]
|
||||
* builder/azure: Fix data disks URI. [GH-9467]
|
||||
* builder/googlecompute: Fix issue with `use_iap` globally changing a user's
|
||||
gcloud project configuration, by temporarily setting "project" via project
|
||||
flag and not via `gcloud config` [GH-9662]
|
||||
* builder/googlecompute: Fix the "secure boot" validation for uefi_compatible
|
||||
images. [GH-9371]
|
||||
* builder/qemu: Only set up localhost port forwarding if skipnatmapping is
|
||||
false. [GH-9479]
|
||||
* builder/vagrant: Fix box file validation for remote box files specified using
|
||||
`source_path` [GH-9660]
|
||||
* builder/vagrant: Improve validation and error handling around synced_folder.
|
||||
Make sure that synced folder can be defined relative to Packer run
|
||||
directory, not the Vagrant output directory. [GH-9577]
|
||||
* builder/virtualbox-vm: Fix regression where builder would fail if the vm had
|
||||
no snapshots. [GH-9435]
|
||||
* builder/vmware-iso: Try checksum remote file instead of local file. [GH-9584]
|
||||
* builder/vmware: Fix a race that occurred when parsing the network config.
|
||||
[GH-9387]
|
||||
* builder/vmware: Update vendor library, enabling retries on 502 errors
|
||||
[GH-9391]
|
||||
* builder/vsphere-clone: Fix SSH public key injection for cloned templates
|
||||
[GH-9507]
|
||||
* builder/vsphere: Clean up folder path to remove leading slashes. [GH-9542]
|
||||
* builder/vsphere: Deduplicate where Firmware is set in vsphere-iso builder
|
||||
[GH-9557]
|
||||
* builder/vsphere: Fix vsphere ToolsSyncTime and ToolsUpgradePolicy [GH-9515]
|
||||
* builder/vsphere: vSphere driver context is no longer cancelled when Packer
|
||||
context is cancelled. [GH-9576]
|
||||
* communicator/winrm: Add the "no_proxy" environment variable option to have
|
||||
winrm bypass the proxy set by the http_proxy or https_proxy environment
|
||||
vars, when connecting to the remote instance. [GH-9267]
|
||||
* core: Do not print download progress bar if a machine-readable UI is chosen.
|
||||
[GH-9448]
|
||||
* post-processor/amazon-import: Add support for retrying RequestLimitExceeded
|
||||
errors when importing an image [GH-9537]
|
||||
* post-processor/docker-import: Fix crash when using docker-import with HCL.
|
||||
[GH-9670]
|
||||
* post-processor/vsphere: Fix password encoding in vsphere post-processor
|
||||
ovftool call [GH-9589]
|
||||
* post-processor/yandex-export: Fix error handling and docs. [GH-9554]
|
||||
* provisioner/ansible-local: Fix agent auth in SSH communicator [GH-9639]
|
||||
* provisioner/ansible: Correct check for whether PackerHttpAddr is implemented
|
||||
or not [GH-9498]
|
||||
* provisioner/ansible: Quote extra-var packer_build_name to handle names with
|
||||
spaces [GH-9590]
|
||||
|
||||
## 1.6.0 (June 09, 2020)
|
||||
|
||||
### BACKWARDS INCOMPATIBILITIES:
|
||||
* builder/vsphere-iso: The deprecated fields `network`, `network_card`,
|
||||
`disk_size`, `disk_thin_provisioned`, and `disk_eagerly_scrub` have been
|
||||
removed. Run `packer fix template.json` to migrate an existing template
|
||||
[GH-9149]
|
||||
|
||||
* For all iso-based builders, the `iso_checksum_type` and `iso_checksum_url`
|
||||
fields have been removed in favor of simply setting the `iso_checksum`
|
||||
field. Use the [packer fix](https://www.packer.io/docs/commands/fix/)
|
||||
command to update a config file. See the [iso_checksum field
|
||||
docs](https://www.packer.io/docs/builders/virtualbox/iso/#iso_checksum) to
|
||||
read more about this. [GH-8437]
|
||||
|
||||
### FEATURES:
|
||||
* **New post-processor** Yandex Export [GH-9124]
|
||||
* builder/amazon: Add SSM Session Manager as a SSH interface connection
|
||||
[GH-9082]
|
||||
* builder/google: Implement iap proxy for googlecompute [GH-9105]
|
||||
* HCL2/core: Add command/console support for HCL2 config files [GH-9359]
|
||||
* HCL2/core: Add command/validate support for HCL2 config files [GH-9346]
|
||||
* HCL2/core: it is now possible to set source fields from the `build` block
|
||||
[GH-9291]
|
||||
|
||||
### IMPROVEMENTS:
|
||||
* builder/amazon: Added new `build` template function field:
|
||||
SourceAMICreationDate [GH-9277]
|
||||
* builder/azure-arm: Support User Assigned Managed Identity [GH-9293]
|
||||
* builder/azure-chroot: Copy data disks between shared image galleries
|
||||
[GH-9323]
|
||||
* builder/googlecompute: Changed default disk size. [GH-9071]
|
||||
* builder/googlecompute: New option to specify storage location for GCP images
|
||||
[GH-9326]
|
||||
* builder/qemu: Add support for using a network bridge [GH-9159]
|
||||
* builder/qemu: Added `skip_nat_mapping` option to skip the communicator (SSH
|
||||
or WinRM) automatic port forward and use the guest port directly. [GH-9307]
|
||||
* builder/qemu: Replace deprecated `ssh_host_port_min` and `ssh_host_port_max`
|
||||
by `host_port_min` and `host_port_max`. [GH-9307]
|
||||
* builder/virtualbox: Add `output_filename` config option to allow user to set
|
||||
a custom filename instead of forcing it to be the same as vm_name.
|
||||
[GH-9174]
|
||||
* builder/vsphere: Add `floppy_label` option. [GH-9187]
|
||||
* builder/vsphere: Add `ip_wait_address` to allow packer to wait for an ip
|
||||
address that fits within the range (cidr address). [GH-9358]
|
||||
* builder/vsphere: Add `tools_sync_time` and `tools_upgrade_policy` options to
|
||||
set time synchronization and automatic VMware Tools upgrade. [GH-9366]
|
||||
* core/hcl: Enable "force", "debug", and "on-error" command line flags for hcl2
|
||||
builds. [GH-9234]
|
||||
* core/hcl: Enable only/except for provisioners and post-processors [GH-9357]
|
||||
* core/hcl: Support named builds in HCL2 templates [GH-9245]
|
||||
* core/interpolation: Add support for specifying a particular key to fetch from
|
||||
the AWS Secrets Manager [GH-9202] [GH-9286]
|
||||
* core: HCL logs now display source type and source name (`type.name`) in logs
|
||||
to differentiate more easily who says what. [GH-9257]
|
||||
* core: update consul and vault dependencies [GH-9205]
|
||||
* core: Update vendored "go-getter" library with checksum fixes.
|
||||
* core: Users can now configure the http bind address of the server launched to
|
||||
serve files from http_directory [GH-9313]
|
||||
* core: When a template contains a deprecated option, Packer will now encourage
|
||||
the user to call `packer fix`. [GH-9325]
|
||||
* post-processor/docker-push: Support pushing multiple tags [GH-9182]
|
||||
* post-processor/docker-tag: Change field name of docker tag to "tags" instead
|
||||
of "tag" since it's a list. Keep "tag" for backwards compatibility.
|
||||
[GH-9183]
|
||||
* provisioner/windows-restart: Display full hostname, instead of just the
|
||||
NetBIOS name [GH-9335]
|
||||
|
||||
### BUG FIXES:
|
||||
* buidler/vsphere-iso: Fix bug validating iso_urls [GH-9321]
|
||||
* builder/azure-arm: Update runtime constants with a valid DataDiskName
|
||||
[GH-9251]
|
||||
* builder/digitalocean: Use correct image type for Droplet creates. [GH-9212]
|
||||
* builder/openstack: Don't error if metadata can't be set. Old versions of
|
||||
openstack don't support that API call. [GH-9198]
|
||||
* builder/vagrant: Use absolute path for package_include files to prevent them
|
||||
from having to be relative to the output vagrant directory. [GH-9260]
|
||||
* builder/virtualbox: Fix bug using checksum files. [GH-9101]
|
||||
* builder/vmware: Fix ssh connection when the guest platform's dhcpcd switches
|
||||
the IP address in-between a build. [GH-9322]
|
||||
* builder/vsphere-iso: Use the Datacenter's VmFolder call instead of manually
|
||||
generating folder path [GH-9342]
|
||||
* builder/vsphere: Add option not to set host during datastore upload. [GH-9100
|
||||
* builder/vsphere: Fix crash in the driver for an interface conversion of
|
||||
types.AnyType nil to types.ManagedObjectReference. [GH-9354]
|
||||
* builder/vsphere: Fix iso config prepare being called incorrectly, which
|
||||
caused `iso_url` field to fail. [GH-9197]
|
||||
* builder/yandex: Do not require 'gpu-standard-v1' platform_id for any GPU-
|
||||
based config. [GH-9356]
|
||||
* core: Ensure HTTP server information `PackerHTTPIP`, `PackerHTTPPort`, and
|
||||
`PackerHTTPAddr` are available via the `build` template engine for all
|
||||
supported builders [GH-9238]
|
||||
* core: Fix `iso_url` to accept SMB shared files UNC and windows network paths.
|
||||
[GH-8954]
|
||||
* core: Fix regression that broke use of pwd when retrieving the checksum from
|
||||
a file [GH-9129].
|
||||
* post-processor/vagrant: Add "provider_override" template option to allow
|
||||
artifacts from the Artifice post-processor [GH-9239]
|
||||
* post-processor/vsphere-template: Add VSphere builder's artifact to vsphere-
|
||||
template's supported types [GH-9146]
|
||||
* postprocessor/artifice: Update various core post-processors to accept
|
||||
artifacts from the Artifice post-processor [GH-9239]
|
||||
* provisioner/ansible-remote: Fix the arg order to make sure that the playbook
|
||||
file is the last item in the call [GH-9279]
|
||||
* provisioner/ansible: Ansible provisioner doesn't force ssh key checking if
|
||||
user wants to use password to connect instead. [GH-9350]
|
||||
* provisioner/inspec: Fix build variables interpolation [GH-9262]
|
||||
* provisioner/powershell: fix interpolation of execute_command in cleanup
|
||||
script call. [GH-9275]
|
||||
* provisioner/powershell: Fix long-wait retry loop caused by cleanup logic
|
||||
[GH-9226]
|
||||
* provisioner/salt-masterless: Ignore the CmdArgs field in hcl2 [GH-9290]
|
||||
|
||||
## 1.5.6 (May 1, 2020)
|
||||
|
||||
### BACKWARDS INCOMPATIBILITIES:
|
||||
* core/hcl2: HCL2 singular blocks: use key/value or name/value depending on how
|
||||
the service names things [GH-9078]
|
||||
* core/hcl2: Maps are now treated as settable arguments as opposed to blocks.
|
||||
For example `tags = {}` instead of `tags {}` [GH-9035]
|
||||
* `packer build` command: removed option to set `parallel=false`, use
|
||||
`-parallel-builds=1` for this.
|
||||
|
||||
### FEATURES:
|
||||
* **New Builder** azure-dtl allows creation of devtestlabs images in Azure
|
||||
[GH-8987]
|
||||
|
||||
* **New Core Feature** provisioners now support a `max_retries` option that can
|
||||
be used for retrying a provisioner on error [GH-9061]
|
||||
|
||||
* **New Post-Processor**: `yandex-export` Upload built image in Yandex Object Storage.
|
||||
|
||||
### IMPROVEMENTS:
|
||||
* builder/azure-arm: Add `boot_diag_storage_account` option for enabling boot
|
||||
diagnostics on a virtual machine [GH-9053]
|
||||
* builder/azure-arm: Add support for setting custom resource names [GH-9028]
|
||||
* builder/azure-arm: Data disk names are now randomly generated [GH-8986]
|
||||
* builder/azure: Add shared image destination for azure-chroot [GH-9021]
|
||||
* builder/azure: Add shared image source for chroot builder [GH-9070]
|
||||
* builder/google: Add support for custom shielded images [GH-8970]
|
||||
* 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/hyperv: Add `boot_order` option to override the default boot order
|
||||
[GH-9046]
|
||||
* builder/oracle-oci: Allow Instance Principal Auth for Oracle OCI builder
|
||||
[GH-8893]
|
||||
* builder/oracle-oci: Update Oracle SDK. [GH-9104]
|
||||
* builder/proxmox: Add ability to add a cloud-init drive [GH-9045]
|
||||
* builder/vsphere: Add `disable_shutdown` option to support manual vm shutdown
|
||||
over the default automatic shutdown step [GH-9095]
|
||||
* builder/vsphere: Add `vgpu_profile` option for specifying vGPU profiles
|
||||
[GH-8946]
|
||||
* builder/vsphere: Add support for EFI Secure Boot [GH-9018]
|
||||
* builder/vsphere: Add support for specifying vGPU profiles [GH-8946]
|
||||
* builder/yandex: Add `target_image_folder_id ` option for changing the folder
|
||||
where a built image will be saved to [GH-9080]
|
||||
* core/hcl2: HCL mode builds now honor -only and -except options [GH-8947]
|
||||
* core/hcl2: Set `packer_build_name` and `packer_builder_type` variables for
|
||||
builder provisioners and post-processors [GH-8956]
|
||||
* core/HCL: HCL mode now honors -only and -except options. [GH-8947]
|
||||
* core: New template function: aws_secretsmanager [GH-9099]
|
||||
* provisioner/ansible: Add `use_proxy` option to not use localhost proxy adapter. Removes
|
||||
* provisioner/ansible: Add option to not use localhost proxy adapter. Removes
|
||||
need for ansible connection_plugin when using WinRM. [GH-8625]
|
||||
* provisioner/powershell: Add `debug_mode` option to help with debugging
|
||||
generated scripts [GH-8996]
|
||||
* provisioner/powershell: Add cleanup step to remove temporarily created
|
||||
scripts; cleanup can be skipped by setting the `skip_clean` option
|
||||
[GH-8908]
|
||||
* builder/yandex: Allow set `target_image_folder_id ` where save built
|
||||
image in [GH-9079]
|
||||
|
||||
### BUG FIXES:
|
||||
* builder/amazon: Fix bug with `launch_block_device_mappings` in spot
|
||||
instances. [GH-8945]
|
||||
* builder/azure-arm: Fix issue where managed image builds were using a
|
||||
different `location` then what was specified in the build configuration
|
||||
[GH-9068]
|
||||
### Bug Fixes:
|
||||
* builder/amazon: Fix bug with launch_block_device_mappings in spot instances.
|
||||
[GH-8945]
|
||||
* builder/azure: Allow Managed Data Disks to be used with Azure Shared Image
|
||||
Gallery [GH-8912]
|
||||
* builder/azure: Fix SSH connection for temporary admin users specified in
|
||||
`ssh_username` [GH-9103]
|
||||
* builder/osc: Make compliant with oAPI spec for Outscale osc-bsu builder
|
||||
[GH-9093]
|
||||
* builder/qemu: Remove `net_device` pre-validation [GH-8979]
|
||||
* builder/tencentcloud: Update builder to handle the
|
||||
InstanceOperationInProgress error [GH-9069]
|
||||
* builder/vsphere-iso: disk_size is no longer required if storage is defined
|
||||
[GH-8975]
|
||||
* builder/vsphere: Add exported files to VSphere artifact [GH-9020]
|
||||
* builder/vsphere: Fix issue where -force is not working with vsphere builders
|
||||
[GH-9039]
|
||||
* 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]
|
||||
@@ -348,11 +35,6 @@
|
||||
|
||||
## 1.5.5 (March 25,2020)
|
||||
|
||||
### BACKWARDS INCOMPATIBILITIES:
|
||||
* core: Interpolation of undefined variables will now error as expected, in
|
||||
previous versions variables were allowed to be set as a command line
|
||||
argument but that was because the validation was being ignored
|
||||
|
||||
### IMPROVEMENTS:
|
||||
* builder/azure: Add support for configurable KeyVault SKU [GH-8879]
|
||||
* builder/hyperv: Add `first_boot_device` setting to allow the selection of the
|
||||
@@ -361,7 +43,7 @@
|
||||
* builder/openstack: Add new `image_auto_accept_members` option [GH-8931]
|
||||
* builder/proxmox: Add ability to specify vga adapter [GH-8892]
|
||||
* builder/proxmox: Add onboot directive support [GH-8935]
|
||||
* builder/tencentcloud: Show tencentcloud image id after copy to destination
|
||||
* builder/tencentcloud: Show tencentcloud image id after copy to desination
|
||||
region. [GH-8763]
|
||||
* builder/vmware-iso: Add `cleanup_remote_cache` config option to [GH-8917]
|
||||
* builder/vmware-iso: Do not perform dial test of NIC when ssh bastion is
|
||||
@@ -387,6 +69,8 @@
|
||||
strings [GH-8829]
|
||||
|
||||
### Bug Fixes:
|
||||
* bilder/proxmox: Bump proxmox-api-go to fix upstream bug where users hit open
|
||||
file limit. [GH-8800]
|
||||
* builder/azure: Fix `winrm_password` attribution and allow users to set
|
||||
`winrm_username` [GH-8928]
|
||||
* builder/azure: Fix azure key vault cleanup failure [GH-8905]
|
||||
@@ -397,8 +81,6 @@
|
||||
to fix SSH authentication issue [GH-8942]
|
||||
* builder/proxmox: Add new validation to catch that template_name cannot
|
||||
contain spaces. [GH-8799]
|
||||
* builder/proxmox: Bump proxmox-api-go to fix upstream bug where users hit open
|
||||
file limit. [GH-8800]
|
||||
* builder/vagrant: Fix path validation in ssh config step. [GH-8826]
|
||||
* builder/virtualbox-vm: Fix crash when VM has no snapshots. [GH-8906]
|
||||
* builder/virtualbox: Remove all floppy controllers before adding a new one.
|
||||
@@ -415,11 +97,8 @@
|
||||
provisioners. [GH-8771]
|
||||
* core: Fix bug where user var recursion could fail intermittently when used
|
||||
with env vars [GH-8875]
|
||||
* core: Interpolation of undefined variables will now error as expected
|
||||
* plugins: Make plugin discovery stricter with respect to periods so that users
|
||||
can disable plugins by renaming the extension [GH-8735]
|
||||
* provisioner/salt: Fix `no_exit_on_failure` config to work correctly as
|
||||
expected. [GH-9119]
|
||||
* provisioner/shell: "inline" config option is now a template engine. [GH-8883]
|
||||
|
||||
## 1.5.4 (February 14, 2020)
|
||||
@@ -576,7 +255,7 @@ making changes for HCL2.
|
||||
|
||||
### BUG FIXES:
|
||||
* builder/amazon: Fix request retry mechanism to launch aws instance [GH-8430]
|
||||
* builder/azure: Fix PollDuration option which was overridden in some clients.
|
||||
* builder/azure: Fix PollDuration option which was overriden in some clients.
|
||||
[GH-8490]
|
||||
* builder/hyperv: Fix bug in checking VM name that could cause flakiness if
|
||||
many VMs are defined. [GH-8357]
|
||||
@@ -670,7 +349,7 @@ making changes for HCL2.
|
||||
## 1.4.4 (October 1, 2019)
|
||||
|
||||
### IMPROVEMENTS:
|
||||
**New Core Feature** Error cleanup provisioner [GH-8155]
|
||||
** new core feature** Error cleanup provisioner [GH-8155]
|
||||
* builder/amazon: Add ability to set `run_volume_tags` [GH-8051]
|
||||
* builder/amazon: Add AWS API call reties on AMI prevalidation [GH-8034]
|
||||
* builder/azure: Refactor client config [GH-8121]
|
||||
@@ -700,7 +379,7 @@ making changes for HCL2.
|
||||
* post-processor/vagrant-cloud: Allow use of the Artifice post-processor with
|
||||
the Vagrant Cloud post-processor [GH-8018] [GH-8027]
|
||||
* post-processor/vsphere: Removed redundant whitelist check for builders,
|
||||
allowing users to use post-processor without the VMWare builder [GH-8064]
|
||||
allowing users to use post-processor withough the VMWare builder [GH-8064]
|
||||
|
||||
### BUG FIXES:
|
||||
* builder/amazon: Fix FleetID crash. [GH-8013]
|
||||
@@ -733,7 +412,7 @@ making changes for HCL2.
|
||||
* builder/virtualbox: LoadSnapshots succeeds even if machine has no snapshots
|
||||
[GH-8096]
|
||||
* builder/vmware: fix dropped test errors [GH-8170]
|
||||
* core: Fix bug where sensitive variables containing commas were not being
|
||||
* core: Fix bug where sensitive variables contianing commas were not being
|
||||
properly sanitized in UI calls. [GH-7997]
|
||||
* core: Fix handling of booleans where "unset" is a value distinct from
|
||||
"false". [GH-8021]
|
||||
@@ -748,7 +427,7 @@ making changes for HCL2.
|
||||
|
||||
### BACKWARDS INCOMPATIBILITIES:
|
||||
* core: "sed" template function has been deprecated in favor of "replace" and
|
||||
"replace_all" functions [GH-8119]
|
||||
"replace_all" functins [GH-8119]
|
||||
|
||||
## 1.4.3 (August 14, 2019)
|
||||
|
||||
@@ -884,14 +563,14 @@ making changes for HCL2.
|
||||
build region. [GH-7691]
|
||||
* builder/amazon: Fix failure that happened when spot_tags was set but ami_tags
|
||||
wasn't [GH-7712]
|
||||
* builder/cloudstack: Update go-cloudstack sdk, fixing compatibility with
|
||||
* builder/cloudstack: Update go-cloudstack sdk, fixing compatability with
|
||||
CloudStack v 4.12 [GH-7694]
|
||||
* builder/proxmox: Update proxmox-api-go dependency, fixing issue calculating
|
||||
VMIDs. [GH-7755]
|
||||
* builder/tencent: Correctly remove tencentcloud temporary keypair. [GH-7787]
|
||||
* core: Allow timestamped AND colorless ui messages [GH-7769]
|
||||
* core: Apply logSecretFilter to output from ui.Say [GH-7739]
|
||||
* core: Fix "make bin" command to use reasonable defaults. [GH-7752]
|
||||
* core: Fix "make bin" command to use reasonbale defaults. [GH-7752]
|
||||
* core: Fix user var interpolation for variables set via -var-file and from
|
||||
command line [GH-7733]
|
||||
* core: machine-readable UI now writes UI calls to logs. [GH-7745]
|
||||
@@ -1128,7 +807,7 @@ making changes for HCL2.
|
||||
* core: make packer inspect not print sensitive variables [GH-7084]
|
||||
* post-processor/google: Add new `guest-os-features` option. [GH-7218]
|
||||
* postprocessor/docker-import: Added `change` support [GH-7127]
|
||||
* provisioner/ansible-remote: add `-o IdentitiesOnly=yes` as a default flag
|
||||
* provisioner/ansible-remote: add `-o IdentitiesOnly=yes`as a default flag
|
||||
[GH-7115]
|
||||
* provisioner/chef-client: Elevated support for chef-client provisioner
|
||||
[GH-7078]
|
||||
@@ -1306,7 +985,7 @@ making changes for HCL2.
|
||||
* builder/amazon: fix bugs relating to spot instances provisioning [GH-6697]
|
||||
[GH-6693]
|
||||
* builder/openstack: fix ssh keypair not attached [GH-6701]
|
||||
* core: progressbar: fix deadlock locking builds after first display [GH-6698]
|
||||
* core: progressbar: fix deadlock locking builds afer first display [GH-6698]
|
||||
|
||||
## 1.3.0 (September 11, 2018)
|
||||
|
||||
@@ -1379,7 +1058,7 @@ making changes for HCL2.
|
||||
waiters. [GH-6649]
|
||||
* builder/azure: Generated password satisfies Azure password requirements
|
||||
[GH-6480]
|
||||
* builder/hyper-v: Builder no longer errors if skip_compaction isn't true when
|
||||
* builder/hyper-v: Buider no longer errors if skip_compaction isn't true when
|
||||
skip_export is true, and compaction efficiency is improved [GH-6393]
|
||||
* builder/lxc: Correctly pass "config" option to "lxc launch". [GH-6563]
|
||||
* builder/lxc: Determine lxc root according to the running user [GH-6543]
|
||||
@@ -1400,7 +1079,7 @@ making changes for HCL2.
|
||||
`execute_command`s [GH-6636]
|
||||
* provisioner/shell-local: Windows inline scripts now default to being appended
|
||||
with ".cmd", fixing a backwards incompatibility in v1.2.5 [GH-6626]
|
||||
* provisioner/windows-restart: Provisioner now works when used in conjunction
|
||||
* provisioner/windows-restart: Provisioner now works when used in conjuction
|
||||
with SSH communicator [GH-6606]
|
||||
|
||||
### BACKWARDS INCOMPATIBILITIES:
|
||||
@@ -1542,7 +1221,7 @@ making changes for HCL2.
|
||||
* builder/virtualbox: Fix broken scancodes in boot_command. [GH-6067]
|
||||
* builder/vmware-iso: Fail in validation if user gives wrong remote_type value.
|
||||
[GH-4563]
|
||||
* builder/vmware: Fixed a case-sensitivity issue when determining the network
|
||||
* builder/vmware: Fixed a case-sensitivity issue when determing the network
|
||||
type during the cloning step in the vmware-vmx builder. [GH-6057]
|
||||
* builder/vmware: Fixes the DHCP lease and configuration pathfinders for VMware
|
||||
Player. [GH-6096]
|
||||
@@ -3663,7 +3342,7 @@ making changes for HCL2.
|
||||
### BUG FIXES:
|
||||
|
||||
* core: default user variable values don't need to be strings. [GH-456]
|
||||
* builder/amazon-chroot: Fix errors with waiting for state change. [GH-459]
|
||||
* builder/amazon-chroot: Fix errors with waitin for state change. [GH-459]
|
||||
* builder/digitalocean: Use proper error message JSON key (DO API change).
|
||||
* communicator/ssh: SCP uploads now work properly when directories
|
||||
contain symlinks. [GH-449]
|
||||
|
||||
+4
-20
@@ -2,21 +2,15 @@
|
||||
|
||||
# builders
|
||||
|
||||
/examples/alicloud/ @chhaj5236 @alexyueer
|
||||
/builder/alicloud/ @chhaj5236 @alexyueer
|
||||
/website/pages/docs/builders/alicloud* @chhaj5236 @alexyueer
|
||||
|
||||
/examples/azure/ @paulmey
|
||||
/builder/azure/ @paulmey
|
||||
/website/pages/docs/builders/azure* @paulmey
|
||||
|
||||
/builder/digitalocean/ @andrewsomething
|
||||
/website/pages/docs/builders/digitalocean* @andrewsomething
|
||||
|
||||
/builder/hyperv/ @taliesins
|
||||
/website/pages/docs/builders/hyperv* @taliesins
|
||||
|
||||
/examples/jdcloud/ @XiaohanLiang @remrain
|
||||
/builder/jdcloud/ @XiaohanLiang @remrain
|
||||
/website/pages/docs/builders/jdcloud* @XiaohanLiang @remrain
|
||||
|
||||
@@ -24,9 +18,7 @@
|
||||
/website/pages/docs/builders/linode* @displague @ctreatma @stvnjacobs @charliekenney23 @phillc
|
||||
|
||||
/builder/lxc/ @ChrisLundquist
|
||||
/website/pages/docs/builders/lxc* @ChrisLundquist
|
||||
/test/fixtures/builder-lxc/ @ChrisLundquist
|
||||
/test/builder_lxc* @ChrisLundquist
|
||||
/website/pages/docs/builders/lxc* @ChrisLundquist
|
||||
|
||||
/builder/lxd/ @ChrisLundquist
|
||||
/website/pages/docs/builders/lxd* @ChrisLundquist
|
||||
@@ -55,23 +47,18 @@
|
||||
/builder/hcloud/ @LKaemmerling
|
||||
/website/pages/docs/builders/hcloud* @LKaemmerling
|
||||
|
||||
/examples/hyperone/ @m110 @gregorybrzeski @ad-m
|
||||
/builder/hyperone/ @m110 @gregorybrzeski @ad-m
|
||||
/builder/hyperone/ @m110 @gregorybrzeski @ad-m
|
||||
/website/pages/docs/builders/hyperone* @m110 @gregorybrzeski @ad-m
|
||||
/test/builder_hyperone* @m110 @gregorybrzeski @ad-m
|
||||
/test/fixtures/builder-hyperone/ @m110 @gregorybrzeski @ad-m
|
||||
|
||||
/examples/ucloud/ @shawnmssu
|
||||
/builder/ucloud/ @shawnmssu
|
||||
/website/pages/docs/builders/ucloud* @shawnmssu
|
||||
|
||||
/builder/yandex/ @GennadySpb @alexanderKhaustov @seukyaso
|
||||
/website/pages/docs/builders/yandex* @GennadySpb @alexanderKhaustov @seukyaso
|
||||
|
||||
/builder/osc/ @marinsalinas @Hakujou
|
||||
/website/pages/docs/builders/osc* @marinsalinas @Hakujou
|
||||
/builder/osc/ @marinsalinas
|
||||
/website/pages/docs/builders/osc* @marinsalinas
|
||||
|
||||
/examples/tencentcloud/ @likexian
|
||||
/builder/tencentcloud/ @likexian
|
||||
/website/pages/docs/builders/tencentcloud* @likexian
|
||||
|
||||
@@ -79,7 +66,6 @@
|
||||
|
||||
# provisioners
|
||||
|
||||
/examples/ansible/ @bhcleek
|
||||
/provisioner/ansible/ @bhcleek
|
||||
/provisioner/converge/ @stevendborrelli
|
||||
|
||||
@@ -89,7 +75,5 @@
|
||||
/post-processor/checksum/ v.tolstov@selfip.ru
|
||||
/post-processor/exoscale-import/ @falzm @mcorbin
|
||||
/post-processor/googlecompute-export/ crunkleton@google.com
|
||||
/post-processor/yandex-export/ @GennadySpb
|
||||
/post-processor/yandex-import/ @GennadySpb
|
||||
/post-processor/vsphere-template/ nelson@bennu.cl
|
||||
/post-processor/ucloud-import/ @shawnmssu
|
||||
|
||||
@@ -120,12 +120,11 @@ fmt-examples:
|
||||
# source files.
|
||||
generate: install-gen-deps ## Generate dynamically generated code
|
||||
@echo "==> removing autogenerated markdown..."
|
||||
@find website/pages/ -type f | xargs grep -l '^<!-- Code generated' | xargs rm -f
|
||||
@find website/pages/ -type f | xargs grep -l '^<!-- Code generated' | xargs rm
|
||||
@echo "==> removing autogenerated code..."
|
||||
@find post-processor common helper template builder provisioner -type f | xargs grep -l '^// Code generated' | xargs rm -f
|
||||
@find post-processor common helper template builder provisioner -type f | xargs grep -l '^// Code generated' | xargs rm
|
||||
go generate ./...
|
||||
go fmt common/bootcommand/boot_command.go
|
||||
go run ./cmd/generate-fixer-deprecations
|
||||
|
||||
generate-check: generate ## Check go code generation is on par
|
||||
@echo "==> Checking that auto-generated code is not changed..."
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# Packer
|
||||
|
||||
[![Build Status][circleci-badge]][circleci]
|
||||
[![Build Status][travis-badge]][travis]
|
||||
[![Windows Build Status][appveyor-badge]][appveyor]
|
||||
[](https://pkg.go.dev/github.com/hashicorp/packer)
|
||||
[![GoDoc][godoc-badge]][godoc]
|
||||
[![GoReportCard][report-badge]][report]
|
||||
[](https://codecov.io/gh/hashicorp/packer)
|
||||
|
||||
[circleci-badge]: https://circleci.com/gh/hashicorp/packer.svg?style=svg
|
||||
[circleci]: https://app.circleci.com/pipelines/github/hashicorp/packer
|
||||
[travis-badge]: https://travis-ci.org/hashicorp/packer.svg?branch=master
|
||||
[travis]: https://travis-ci.org/hashicorp/packer
|
||||
[appveyor-badge]: https://ci.appveyor.com/api/projects/status/miavlgnp989e5obc/branch/master?svg=true
|
||||
[appveyor]: https://ci.appveyor.com/project/hashicorp/packer
|
||||
[godoc-badge]: https://godoc.org/github.com/hashicorp/packer?status.svg
|
||||
@@ -95,20 +95,3 @@ See
|
||||
[CONTRIBUTING.md](https://github.com/hashicorp/packer/blob/master/.github/CONTRIBUTING.md)
|
||||
for best practices and instructions on setting up your development environment
|
||||
to work on Packer.
|
||||
|
||||
## Unmaintained Plugins
|
||||
As contributors' circumstances change, development on a community maintained
|
||||
plugin can slow. When this happens, the Packer team may mark a plugin as
|
||||
unmaintained, to clearly signal the plugin's status to users.
|
||||
|
||||
What does **unmaintained** mean?
|
||||
|
||||
1. The code repository and all commit history will still be available.
|
||||
1. Documentation will remain on the Packer website.
|
||||
1. Issues and pull requests are monitored as a best effort.
|
||||
1. No active development will be performed by the Packer team.
|
||||
|
||||
If anyone form them community is interested in maintaining a community
|
||||
supported plugin, please feel free to submit contributions via a pull-
|
||||
request for review; reviews are generally prioritized over feature work
|
||||
when possible. For a list of open plugin issues and pending feature requests see the [Packer Issue Tracker](https://github.com/hashicorp/packer/issues/).
|
||||
|
||||
@@ -18,26 +18,26 @@ import (
|
||||
|
||||
// Config of alicloud
|
||||
type AlicloudAccessConfig struct {
|
||||
// Alicloud access key must be provided unless `profile` is set, but it can
|
||||
// also be sourced from the `ALICLOUD_ACCESS_KEY` environment variable.
|
||||
AlicloudAccessKey string `mapstructure:"access_key" required:"true"`
|
||||
// Alicloud secret key must be provided unless `profile` is set, but it can
|
||||
// also be sourced from the `ALICLOUD_SECRET_KEY` environment variable.
|
||||
AlicloudSecretKey string `mapstructure:"secret_key" required:"true"`
|
||||
// Alicloud region must be provided unless `profile` is set, but it can
|
||||
// also be sourced from the `ALICLOUD_REGION` environment variable.
|
||||
AlicloudRegion string `mapstructure:"region" required:"true"`
|
||||
// This is the Alicloud access key. It must be provided when profile not exist, but it can also be
|
||||
// sourced from the ALICLOUD_ACCESS_KEY environment variable.
|
||||
AlicloudAccessKey string `mapstructure:"access_key" required:"false"`
|
||||
// This is the Alicloud secret key. It must be provided when profile not exist, but it can also be
|
||||
// sourced from the ALICLOUD_SECRET_KEY environment variable.
|
||||
AlicloudSecretKey string `mapstructure:"secret_key" required:"false"`
|
||||
// This is the Alicloud region. It must be provided when profile not exist, but it can also be
|
||||
// sourced from the ALICLOUD_REGION environment variables.
|
||||
AlicloudRegion string `mapstructure:"region" required:"false"`
|
||||
// The region validation can be skipped if this value is true, the default
|
||||
// value is false.
|
||||
AlicloudSkipValidation bool `mapstructure:"skip_region_validation" required:"false"`
|
||||
// The image validation can be skipped if this value is true, the default
|
||||
// value is false.
|
||||
AlicloudSkipImageValidation bool `mapstructure:"skip_image_validation" required:"false"`
|
||||
// Alicloud profile must be set unless `access_key` is set; it can also be
|
||||
// sourced from the `ALICLOUD_PROFILE` environment variable.
|
||||
// This is th Alicloud profile. If access_key not exist, is must be provided, but it can also be
|
||||
// sourced from the ALICLOUD_PROFILE environment variables.
|
||||
AlicloudProfile string `mapstructure:"profile" required:"false"`
|
||||
// Alicloud shared credentials file path. If this file exists, access and
|
||||
// secret keys will be read from this file.
|
||||
// This is the Alicloud shared credentials file path. If this file path exist, os will read access key
|
||||
// and secret key from this file.
|
||||
AlicloudSharedCredentialsFile string `mapstructure:"shared_credentials_file" required:"false"`
|
||||
// STS access token, can be set through template or by exporting as
|
||||
// environment variable such as `export SECURITY_TOKEN=value`.
|
||||
|
||||
@@ -10,14 +10,14 @@ import (
|
||||
// FlatAlicloudDiskDevice is an auto-generated flat version of AlicloudDiskDevice.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatAlicloudDiskDevice struct {
|
||||
DiskName *string `mapstructure:"disk_name" required:"false" cty:"disk_name" hcl:"disk_name"`
|
||||
DiskCategory *string `mapstructure:"disk_category" required:"false" cty:"disk_category" hcl:"disk_category"`
|
||||
DiskSize *int `mapstructure:"disk_size" required:"false" cty:"disk_size" hcl:"disk_size"`
|
||||
SnapshotId *string `mapstructure:"disk_snapshot_id" required:"false" cty:"disk_snapshot_id" hcl:"disk_snapshot_id"`
|
||||
Description *string `mapstructure:"disk_description" required:"false" cty:"disk_description" hcl:"disk_description"`
|
||||
DeleteWithInstance *bool `mapstructure:"disk_delete_with_instance" required:"false" cty:"disk_delete_with_instance" hcl:"disk_delete_with_instance"`
|
||||
Device *string `mapstructure:"disk_device" required:"false" cty:"disk_device" hcl:"disk_device"`
|
||||
Encrypted *bool `mapstructure:"disk_encrypted" required:"false" cty:"disk_encrypted" hcl:"disk_encrypted"`
|
||||
DiskName *string `mapstructure:"disk_name" required:"false" cty:"disk_name"`
|
||||
DiskCategory *string `mapstructure:"disk_category" required:"false" cty:"disk_category"`
|
||||
DiskSize *int `mapstructure:"disk_size" required:"false" cty:"disk_size"`
|
||||
SnapshotId *string `mapstructure:"disk_snapshot_id" required:"false" cty:"disk_snapshot_id"`
|
||||
Description *string `mapstructure:"disk_description" required:"false" cty:"disk_description"`
|
||||
DeleteWithInstance *bool `mapstructure:"disk_delete_with_instance" required:"false" cty:"disk_delete_with_instance"`
|
||||
Device *string `mapstructure:"disk_device" required:"false" cty:"disk_device"`
|
||||
Encrypted *bool `mapstructure:"disk_encrypted" required:"false" cty:"disk_encrypted"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatAlicloudDiskDevice.
|
||||
@@ -47,106 +47,100 @@ func (*FlatAlicloudDiskDevice) HCL2Spec() map[string]hcldec.Spec {
|
||||
// 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" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
AlicloudAccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key" hcl:"access_key"`
|
||||
AlicloudSecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key" hcl:"secret_key"`
|
||||
AlicloudRegion *string `mapstructure:"region" required:"true" cty:"region" hcl:"region"`
|
||||
AlicloudSkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation" hcl:"skip_region_validation"`
|
||||
AlicloudSkipImageValidation *bool `mapstructure:"skip_image_validation" required:"false" cty:"skip_image_validation" hcl:"skip_image_validation"`
|
||||
AlicloudProfile *string `mapstructure:"profile" required:"false" cty:"profile" hcl:"profile"`
|
||||
AlicloudSharedCredentialsFile *string `mapstructure:"shared_credentials_file" required:"false" cty:"shared_credentials_file" hcl:"shared_credentials_file"`
|
||||
SecurityToken *string `mapstructure:"security_token" required:"false" cty:"security_token" hcl:"security_token"`
|
||||
AlicloudImageName *string `mapstructure:"image_name" required:"true" cty:"image_name" hcl:"image_name"`
|
||||
AlicloudImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version" hcl:"image_version"`
|
||||
AlicloudImageDescription *string `mapstructure:"image_description" required:"false" cty:"image_description" hcl:"image_description"`
|
||||
AlicloudImageShareAccounts []string `mapstructure:"image_share_account" required:"false" cty:"image_share_account" hcl:"image_share_account"`
|
||||
AlicloudImageUNShareAccounts []string `mapstructure:"image_unshare_account" cty:"image_unshare_account" hcl:"image_unshare_account"`
|
||||
AlicloudImageDestinationRegions []string `mapstructure:"image_copy_regions" required:"false" cty:"image_copy_regions" hcl:"image_copy_regions"`
|
||||
AlicloudImageDestinationNames []string `mapstructure:"image_copy_names" required:"false" cty:"image_copy_names" hcl:"image_copy_names"`
|
||||
ImageEncrypted *bool `mapstructure:"image_encrypted" required:"false" cty:"image_encrypted" hcl:"image_encrypted"`
|
||||
AlicloudImageForceDelete *bool `mapstructure:"image_force_delete" required:"false" cty:"image_force_delete" hcl:"image_force_delete"`
|
||||
AlicloudImageForceDeleteSnapshots *bool `mapstructure:"image_force_delete_snapshots" required:"false" cty:"image_force_delete_snapshots" hcl:"image_force_delete_snapshots"`
|
||||
AlicloudImageForceDeleteInstances *bool `mapstructure:"image_force_delete_instances" cty:"image_force_delete_instances" hcl:"image_force_delete_instances"`
|
||||
AlicloudImageIgnoreDataDisks *bool `mapstructure:"image_ignore_data_disks" required:"false" cty:"image_ignore_data_disks" hcl:"image_ignore_data_disks"`
|
||||
AlicloudImageTags map[string]string `mapstructure:"tags" required:"false" cty:"tags" hcl:"tags"`
|
||||
AlicloudImageTag []hcl2template.FlatKeyValue `mapstructure:"tag" required:"false" cty:"tag" hcl:"tag"`
|
||||
ECSSystemDiskMapping *FlatAlicloudDiskDevice `mapstructure:"system_disk_mapping" required:"false" cty:"system_disk_mapping" hcl:"system_disk_mapping"`
|
||||
ECSImagesDiskMappings []FlatAlicloudDiskDevice `mapstructure:"image_disk_mappings" required:"false" cty:"image_disk_mappings" hcl:"image_disk_mappings"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" cty:"associate_public_ip_address" hcl:"associate_public_ip_address"`
|
||||
ZoneId *string `mapstructure:"zone_id" required:"false" cty:"zone_id" hcl:"zone_id"`
|
||||
IOOptimized *bool `mapstructure:"io_optimized" required:"false" cty:"io_optimized" hcl:"io_optimized"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type" hcl:"instance_type"`
|
||||
Description *string `mapstructure:"description" cty:"description" hcl:"description"`
|
||||
AlicloudSourceImage *string `mapstructure:"source_image" required:"true" cty:"source_image" hcl:"source_image"`
|
||||
ForceStopInstance *bool `mapstructure:"force_stop_instance" required:"false" cty:"force_stop_instance" hcl:"force_stop_instance"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"`
|
||||
SecurityGroupName *string `mapstructure:"security_group_name" required:"false" cty:"security_group_name" hcl:"security_group_name"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file" hcl:"user_data_file"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"`
|
||||
VpcName *string `mapstructure:"vpc_name" required:"false" cty:"vpc_name" hcl:"vpc_name"`
|
||||
CidrBlock *string `mapstructure:"vpc_cidr_block" required:"false" cty:"vpc_cidr_block" hcl:"vpc_cidr_block"`
|
||||
VSwitchId *string `mapstructure:"vswitch_id" required:"false" cty:"vswitch_id" hcl:"vswitch_id"`
|
||||
VSwitchName *string `mapstructure:"vswitch_name" required:"false" cty:"vswitch_name" hcl:"vswitch_name"`
|
||||
InstanceName *string `mapstructure:"instance_name" required:"false" cty:"instance_name" hcl:"instance_name"`
|
||||
InternetChargeType *string `mapstructure:"internet_charge_type" required:"false" cty:"internet_charge_type" hcl:"internet_charge_type"`
|
||||
InternetMaxBandwidthOut *int `mapstructure:"internet_max_bandwidth_out" required:"false" cty:"internet_max_bandwidth_out" hcl:"internet_max_bandwidth_out"`
|
||||
WaitSnapshotReadyTimeout *int `mapstructure:"wait_snapshot_ready_timeout" required:"false" cty:"wait_snapshot_ready_timeout" hcl:"wait_snapshot_ready_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
|
||||
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" undocumented:"true" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
|
||||
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
|
||||
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"`
|
||||
SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"`
|
||||
SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"`
|
||||
WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
||||
SSHPrivateIp *bool `mapstructure:"ssh_private_ip" required:"false" cty:"ssh_private_ip" hcl:"ssh_private_ip"`
|
||||
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"`
|
||||
AlicloudAccessKey *string `mapstructure:"access_key" required:"false" cty:"access_key"`
|
||||
AlicloudSecretKey *string `mapstructure:"secret_key" required:"false" cty:"secret_key"`
|
||||
AlicloudRegion *string `mapstructure:"region" required:"false" cty:"region"`
|
||||
AlicloudSkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
|
||||
AlicloudSkipImageValidation *bool `mapstructure:"skip_image_validation" required:"false" cty:"skip_image_validation"`
|
||||
AlicloudProfile *string `mapstructure:"profile" required:"false" cty:"profile"`
|
||||
AlicloudSharedCredentialsFile *string `mapstructure:"shared_credentials_file" required:"false" cty:"shared_credentials_file"`
|
||||
SecurityToken *string `mapstructure:"security_token" required:"false" cty:"security_token"`
|
||||
AlicloudImageName *string `mapstructure:"image_name" required:"true" cty:"image_name"`
|
||||
AlicloudImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version"`
|
||||
AlicloudImageDescription *string `mapstructure:"image_description" required:"false" cty:"image_description"`
|
||||
AlicloudImageShareAccounts []string `mapstructure:"image_share_account" required:"false" cty:"image_share_account"`
|
||||
AlicloudImageUNShareAccounts []string `mapstructure:"image_unshare_account" cty:"image_unshare_account"`
|
||||
AlicloudImageDestinationRegions []string `mapstructure:"image_copy_regions" required:"false" cty:"image_copy_regions"`
|
||||
AlicloudImageDestinationNames []string `mapstructure:"image_copy_names" required:"false" cty:"image_copy_names"`
|
||||
ImageEncrypted *bool `mapstructure:"image_encrypted" required:"false" cty:"image_encrypted"`
|
||||
AlicloudImageForceDelete *bool `mapstructure:"image_force_delete" required:"false" cty:"image_force_delete"`
|
||||
AlicloudImageForceDeleteSnapshots *bool `mapstructure:"image_force_delete_snapshots" required:"false" cty:"image_force_delete_snapshots"`
|
||||
AlicloudImageForceDeleteInstances *bool `mapstructure:"image_force_delete_instances" cty:"image_force_delete_instances"`
|
||||
AlicloudImageIgnoreDataDisks *bool `mapstructure:"image_ignore_data_disks" required:"false" cty:"image_ignore_data_disks"`
|
||||
AlicloudImageTags map[string]string `mapstructure:"tags" required:"false" cty:"tags"`
|
||||
AlicloudImageTag []hcl2template.FlatNameValue `mapstructure:"tag" required:"false" cty:"tag"`
|
||||
ECSSystemDiskMapping *FlatAlicloudDiskDevice `mapstructure:"system_disk_mapping" required:"false" cty:"system_disk_mapping"`
|
||||
ECSImagesDiskMappings []FlatAlicloudDiskDevice `mapstructure:"image_disk_mappings" required:"false" cty:"image_disk_mappings"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" cty:"associate_public_ip_address"`
|
||||
ZoneId *string `mapstructure:"zone_id" required:"false" cty:"zone_id"`
|
||||
IOOptimized *bool `mapstructure:"io_optimized" required:"false" cty:"io_optimized"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
|
||||
Description *string `mapstructure:"description" cty:"description"`
|
||||
AlicloudSourceImage *string `mapstructure:"source_image" required:"true" cty:"source_image"`
|
||||
ForceStopInstance *bool `mapstructure:"force_stop_instance" required:"false" cty:"force_stop_instance"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
|
||||
SecurityGroupName *string `mapstructure:"security_group_name" required:"false" cty:"security_group_name"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
|
||||
VpcName *string `mapstructure:"vpc_name" required:"false" cty:"vpc_name"`
|
||||
CidrBlock *string `mapstructure:"vpc_cidr_block" required:"false" cty:"vpc_cidr_block"`
|
||||
VSwitchId *string `mapstructure:"vswitch_id" required:"false" cty:"vswitch_id"`
|
||||
VSwitchName *string `mapstructure:"vswitch_name" required:"false" cty:"vswitch_name"`
|
||||
InstanceName *string `mapstructure:"instance_name" required:"false" cty:"instance_name"`
|
||||
InternetChargeType *string `mapstructure:"internet_charge_type" required:"false" cty:"internet_charge_type"`
|
||||
InternetMaxBandwidthOut *int `mapstructure:"internet_max_bandwidth_out" required:"false" cty:"internet_max_bandwidth_out"`
|
||||
WaitSnapshotReadyTimeout *int `mapstructure:"wait_snapshot_ready_timeout" required:"false" cty:"wait_snapshot_ready_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
|
||||
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" cty:"temporary_key_pair_name"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
||||
SSHPrivateIp *bool `mapstructure:"ssh_private_ip" required:"false" cty:"ssh_private_ip"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
@@ -189,7 +183,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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())},
|
||||
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
|
||||
@@ -221,14 +215,10 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
||||
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
||||
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
||||
"ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false},
|
||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
||||
@@ -239,7 +229,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
||||
@@ -254,7 +243,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
||||
"winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
|
||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
||||
|
||||
@@ -136,67 +136,67 @@ type AlicloudDiskDevices struct {
|
||||
}
|
||||
|
||||
type AlicloudImageConfig struct {
|
||||
// The name of the user-defined image, [2, 128] English or Chinese
|
||||
// characters. It must begin with an uppercase/lowercase letter or a
|
||||
// Chinese character, and may contain numbers, `_` or `-`. It cannot begin
|
||||
// with `http://` or `https://`.
|
||||
AlicloudImageName string `mapstructure:"image_name" required:"true"`
|
||||
// The version number of the image, with a length limit of 1 to 40 English
|
||||
// characters.
|
||||
AlicloudImageVersion string `mapstructure:"image_version" required:"false"`
|
||||
// The description of the image, with a length limit of 0 to 256
|
||||
// characters. Leaving it blank means null, which is the default value. It
|
||||
// The name of the user-defined image, [2, 128]
|
||||
// English or Chinese characters. It must begin with an uppercase/lowercase
|
||||
// letter or a Chinese character, and may contain numbers, _ or -. It
|
||||
// cannot begin with `http://` or `https://`.
|
||||
AlicloudImageName string `mapstructure:"image_name" required:"true"`
|
||||
// The version number of the image, with a length
|
||||
// limit of 1 to 40 English characters.
|
||||
AlicloudImageVersion string `mapstructure:"image_version" required:"false"`
|
||||
// The description of the image, with a length
|
||||
// limit of 0 to 256 characters. Leaving it blank means null, which is the
|
||||
// default value. It cannot begin with `http://` or `https://`.
|
||||
AlicloudImageDescription string `mapstructure:"image_description" required:"false"`
|
||||
// The IDs of to-be-added Aliyun accounts to which the image is shared. The
|
||||
// number of accounts is 1 to 10. If number of accounts is greater than 10,
|
||||
// this parameter is ignored.
|
||||
// The IDs of to-be-added Aliyun
|
||||
// accounts to which the image is shared. The number of accounts is 1 to 10.
|
||||
// If number of accounts is greater than 10, this parameter is ignored.
|
||||
AlicloudImageShareAccounts []string `mapstructure:"image_share_account" required:"false"`
|
||||
AlicloudImageUNShareAccounts []string `mapstructure:"image_unshare_account"`
|
||||
// Copy to the destination regionIds.
|
||||
AlicloudImageDestinationRegions []string `mapstructure:"image_copy_regions" required:"false"`
|
||||
// The name of the destination image, [2, 128] English or Chinese
|
||||
// characters. It must begin with an uppercase/lowercase letter or a
|
||||
// Chinese character, and may contain numbers, _ or -. It cannot begin with
|
||||
// `http://` or `https://`.
|
||||
// The name of the destination image,
|
||||
// [2, 128] English or Chinese characters. It must begin with an
|
||||
// uppercase/lowercase letter or a Chinese character, and may contain numbers,
|
||||
// _ or -. It cannot begin with `http://` or `https://`.
|
||||
AlicloudImageDestinationNames []string `mapstructure:"image_copy_names" required:"false"`
|
||||
// Whether or not to encrypt the target images, including those
|
||||
// copied if image_copy_regions is specified. If this option is set to
|
||||
// true, a temporary image will be created from the provisioned instance in
|
||||
// the main region and an encrypted copy will be generated in the same
|
||||
// region. By default, Packer will keep the encryption setting to what it
|
||||
// was in the source image.
|
||||
// Whether or not to encrypt the target images, including those copied if image_copy_regions is specified. If this option
|
||||
// is set to true, a temporary image will be created from the provisioned
|
||||
// instance in the main region and an encrypted copy will be generated in the
|
||||
// same region. By default, Packer will keep the encryption setting to what
|
||||
// it was in the source image.
|
||||
ImageEncrypted config.Trilean `mapstructure:"image_encrypted" required:"false"`
|
||||
// If this value is true, when the target image names including those
|
||||
// copied are duplicated with existing images, it will delete the existing
|
||||
// images and then create the target images, otherwise, the creation will
|
||||
// fail. The default value is false. Check `image_name` and
|
||||
// `image_copy_names` options for names of target images. If
|
||||
// [-force](/docs/commands/build#force) option is provided in `build`
|
||||
// command, this option can be omitted and taken as true.
|
||||
// [-force](/docs/commands/build#force) option is
|
||||
// provided in `build` command, this option can be omitted and taken as
|
||||
// true.
|
||||
AlicloudImageForceDelete bool `mapstructure:"image_force_delete" required:"false"`
|
||||
// If this value is true, when delete the duplicated existing images, the
|
||||
// source snapshots of those images will be delete either. If
|
||||
// [-force](/docs/commands/build#force) option is provided in `build`
|
||||
// command, this option can be omitted and taken as true.
|
||||
// [-force](/docs/commands/build#force) option is
|
||||
// provided in `build` command, this option can be omitted and taken as
|
||||
// true.
|
||||
AlicloudImageForceDeleteSnapshots bool `mapstructure:"image_force_delete_snapshots" required:"false"`
|
||||
AlicloudImageForceDeleteInstances bool `mapstructure:"image_force_delete_instances"`
|
||||
// If this value is true, the image created will not include any snapshot
|
||||
// of data disks. This option would be useful for any circumstance that
|
||||
// default data disks with instance types are not concerned. The default
|
||||
// value is false.
|
||||
// If this value is true, the image
|
||||
// created will not include any snapshot of data disks. This option would be
|
||||
// useful for any circumstance that default data disks with instance types are
|
||||
// not concerned. The default value is false.
|
||||
AlicloudImageIgnoreDataDisks bool `mapstructure:"image_ignore_data_disks" required:"false"`
|
||||
// The region validation can be skipped if this value is true, the default
|
||||
// value is false.
|
||||
// The region validation can be skipped
|
||||
// if this value is true, the default value is false.
|
||||
AlicloudImageSkipRegionValidation bool `mapstructure:"skip_region_validation" required:"false"`
|
||||
// Key/value pair tags applied to the destination image and relevant
|
||||
// snapshots.
|
||||
// Tags applied to the destination image and relevant snapshots.
|
||||
AlicloudImageTags map[string]string `mapstructure:"tags" required:"false"`
|
||||
// Same as [`tags`](#tags) but defined as a singular repeatable block
|
||||
// containing a `key` and a `value` field. In HCL2 mode the
|
||||
// containing a `name` and a `value` field. In HCL2 mode the
|
||||
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
AlicloudImageTag hcl2template.KeyValues `mapstructure:"tag" required:"false"`
|
||||
AlicloudImageTag hcl2template.NameValues `mapstructure:"tag" required:"false"`
|
||||
AlicloudDiskDevices `mapstructure:",squash"`
|
||||
}
|
||||
|
||||
|
||||
@@ -160,15 +160,15 @@ type Config struct {
|
||||
//criteria provided in `source_ami_filter`; this pins the AMI returned by the
|
||||
//filter, but will cause Packer to fail if the `source_ami` does not exist.
|
||||
SourceAmiFilter awscommon.AmiFilterOptions `mapstructure:"source_ami_filter" required:"false"`
|
||||
// Key/value pair tags to apply to the volumes that are *launched*. This is
|
||||
// a [template engine](/docs/templates/engine), see [Build template
|
||||
// Tags to apply to the volumes that are *launched*. This is a [template
|
||||
// engine](/docs/templates/engine), see [Build template
|
||||
// data](#build-template-data) for more information.
|
||||
RootVolumeTags map[string]string `mapstructure:"root_volume_tags" required:"false"`
|
||||
// Same as [`root_volume_tags`](#root_volume_tags) but defined as a
|
||||
// singular block containing a `key` and a `value` field. In HCL2 mode the
|
||||
// singular block containing a `name` and a `value` field. In HCL2 mode the
|
||||
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
RootVolumeTag hcl2template.KeyValues `mapstructure:"root_volume_tag" required:"false"`
|
||||
RootVolumeTag hcl2template.NameValues `mapstructure:"root_volume_tag" required:"false"`
|
||||
// what architecture to use when registering the final AMI; valid options
|
||||
// are "x86_64" or "arm64". Defaults to "x86_64".
|
||||
Architecture string `mapstructure:"ami_architecture" required:"false"`
|
||||
|
||||
@@ -11,67 +11,67 @@ 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" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name" hcl:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description" hcl:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type" hcl:"ami_virtualization_type"`
|
||||
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users" hcl:"ami_users"`
|
||||
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups" hcl:"ami_groups"`
|
||||
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes" hcl:"ami_product_codes"`
|
||||
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions" hcl:"ami_regions"`
|
||||
AMISkipRegionValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation" hcl:"skip_region_validation"`
|
||||
AMITags map[string]string `mapstructure:"tags" required:"false" cty:"tags" hcl:"tags"`
|
||||
AMITag []hcl2template.FlatKeyValue `mapstructure:"tag" required:"false" cty:"tag" hcl:"tag"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support" hcl:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support" hcl:"sriov_support"`
|
||||
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister" hcl:"force_deregister"`
|
||||
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot" hcl:"force_delete_snapshot"`
|
||||
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot" hcl:"encrypt_boot"`
|
||||
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"`
|
||||
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids" hcl:"region_kms_key_ids"`
|
||||
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region" hcl:"skip_save_build_region"`
|
||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags" hcl:"snapshot_tags"`
|
||||
SnapshotTag []hcl2template.FlatKeyValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag" hcl:"snapshot_tag"`
|
||||
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users" hcl:"snapshot_users"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups" hcl:"snapshot_groups"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key" hcl:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2" hcl:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages" hcl:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify" hcl:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries" hcl:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code" hcl:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile" hcl:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region" hcl:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key" hcl:"secret_key"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" hcl2-schema-generator:"ami_block_device_mappings,direct" required:"false" cty:"ami_block_device_mappings" hcl:"ami_block_device_mappings"`
|
||||
ChrootMounts [][]string `mapstructure:"chroot_mounts" required:"false" cty:"chroot_mounts" hcl:"chroot_mounts"`
|
||||
CommandWrapper *string `mapstructure:"command_wrapper" required:"false" cty:"command_wrapper" hcl:"command_wrapper"`
|
||||
CopyFiles []string `mapstructure:"copy_files" required:"false" cty:"copy_files" hcl:"copy_files"`
|
||||
DevicePath *string `mapstructure:"device_path" required:"false" cty:"device_path" hcl:"device_path"`
|
||||
NVMEDevicePath *string `mapstructure:"nvme_device_path" required:"false" cty:"nvme_device_path" hcl:"nvme_device_path"`
|
||||
FromScratch *bool `mapstructure:"from_scratch" required:"false" cty:"from_scratch" hcl:"from_scratch"`
|
||||
MountOptions []string `mapstructure:"mount_options" required:"false" cty:"mount_options" hcl:"mount_options"`
|
||||
MountPartition *string `mapstructure:"mount_partition" required:"false" cty:"mount_partition" hcl:"mount_partition"`
|
||||
MountPath *string `mapstructure:"mount_path" required:"false" cty:"mount_path" hcl:"mount_path"`
|
||||
PostMountCommands []string `mapstructure:"post_mount_commands" required:"false" cty:"post_mount_commands" hcl:"post_mount_commands"`
|
||||
PreMountCommands []string `mapstructure:"pre_mount_commands" required:"false" cty:"pre_mount_commands" hcl:"pre_mount_commands"`
|
||||
RootDeviceName *string `mapstructure:"root_device_name" required:"false" cty:"root_device_name" hcl:"root_device_name"`
|
||||
RootVolumeSize *int64 `mapstructure:"root_volume_size" required:"false" cty:"root_volume_size" hcl:"root_volume_size"`
|
||||
RootVolumeType *string `mapstructure:"root_volume_type" required:"false" cty:"root_volume_type" hcl:"root_volume_type"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami" hcl:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter" hcl:"source_ami_filter"`
|
||||
RootVolumeTags map[string]string `mapstructure:"root_volume_tags" required:"false" cty:"root_volume_tags" hcl:"root_volume_tags"`
|
||||
RootVolumeTag []hcl2template.FlatKeyValue `mapstructure:"root_volume_tag" required:"false" cty:"root_volume_tag" hcl:"root_volume_tag"`
|
||||
Architecture *string `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture" hcl:"ami_architecture"`
|
||||
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"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type"`
|
||||
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users"`
|
||||
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups"`
|
||||
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes"`
|
||||
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions"`
|
||||
AMISkipRegionValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
|
||||
AMITags map[string]string `mapstructure:"tags" required:"false" cty:"tags"`
|
||||
AMITag []hcl2template.FlatNameValue `mapstructure:"tag" required:"false" cty:"tag"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
|
||||
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
|
||||
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
|
||||
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
|
||||
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
|
||||
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
|
||||
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
|
||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
|
||||
SnapshotTag []hcl2template.FlatNameValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag"`
|
||||
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine"`
|
||||
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" hcl2-schema-generator:"ami_block_device_mappings,direct" required:"false" cty:"ami_block_device_mappings"`
|
||||
ChrootMounts [][]string `mapstructure:"chroot_mounts" required:"false" cty:"chroot_mounts"`
|
||||
CommandWrapper *string `mapstructure:"command_wrapper" required:"false" cty:"command_wrapper"`
|
||||
CopyFiles []string `mapstructure:"copy_files" required:"false" cty:"copy_files"`
|
||||
DevicePath *string `mapstructure:"device_path" required:"false" cty:"device_path"`
|
||||
NVMEDevicePath *string `mapstructure:"nvme_device_path" required:"false" cty:"nvme_device_path"`
|
||||
FromScratch *bool `mapstructure:"from_scratch" required:"false" cty:"from_scratch"`
|
||||
MountOptions []string `mapstructure:"mount_options" required:"false" cty:"mount_options"`
|
||||
MountPartition *string `mapstructure:"mount_partition" required:"false" cty:"mount_partition"`
|
||||
MountPath *string `mapstructure:"mount_path" required:"false" cty:"mount_path"`
|
||||
PostMountCommands []string `mapstructure:"post_mount_commands" required:"false" cty:"post_mount_commands"`
|
||||
PreMountCommands []string `mapstructure:"pre_mount_commands" required:"false" cty:"pre_mount_commands"`
|
||||
RootDeviceName *string `mapstructure:"root_device_name" required:"false" cty:"root_device_name"`
|
||||
RootVolumeSize *int64 `mapstructure:"root_volume_size" required:"false" cty:"root_volume_size"`
|
||||
RootVolumeType *string `mapstructure:"root_volume_type" required:"false" cty:"root_volume_type"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
|
||||
RootVolumeTags map[string]string `mapstructure:"root_volume_tags" required:"false" cty:"root_volume_tags"`
|
||||
RootVolumeTag []hcl2template.FlatNameValue `mapstructure:"root_volume_tag" required:"false" cty:"root_volume_tag"`
|
||||
Architecture *string `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
@@ -102,7 +102,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
|
||||
@@ -112,7 +112,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
|
||||
@@ -145,7 +145,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.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.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
}
|
||||
return s
|
||||
|
||||
@@ -116,8 +116,6 @@ type AccessConfig struct {
|
||||
// credential types) and GetFederationToken (for federation\_token
|
||||
// credential types) for more details.
|
||||
//
|
||||
// JSON example:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "vault_aws_engine": {
|
||||
@@ -127,16 +125,6 @@ type AccessConfig struct {
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// HCL2 example:
|
||||
//
|
||||
// ```hcl
|
||||
// vault_aws_engine {
|
||||
// name = "myrole"
|
||||
// role_arn = "myarn"
|
||||
// ttl = "3600s"
|
||||
// }
|
||||
// ```
|
||||
VaultAWSEngine VaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false"`
|
||||
|
||||
getEC2Connection func() ec2iface.EC2API
|
||||
@@ -200,7 +188,7 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
||||
|
||||
cp, err := c.session.Config.Credentials.Get()
|
||||
|
||||
if IsAWSErr(err, "NoCredentialProviders", "") {
|
||||
if isAWSErr(err, "NoCredentialProviders", "") {
|
||||
return nil, fmt.Errorf("No valid credential sources found for AWS Builder. " +
|
||||
"Please see https://www.packer.io/docs/builders/amazon#specifying-amazon-credentials " +
|
||||
"for more information on providing credentials for the AWS Builder.")
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
// FlatVaultAWSEngineOptions is an auto-generated flat version of VaultAWSEngineOptions.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatVaultAWSEngineOptions struct {
|
||||
Name *string `mapstructure:"name" cty:"name" hcl:"name"`
|
||||
RoleARN *string `mapstructure:"role_arn" cty:"role_arn" hcl:"role_arn"`
|
||||
TTL *string `mapstructure:"ttl" required:"false" cty:"ttl" hcl:"ttl"`
|
||||
EngineName *string `mapstructure:"engine_name" cty:"engine_name" hcl:"engine_name"`
|
||||
Name *string `mapstructure:"name" cty:"name"`
|
||||
RoleARN *string `mapstructure:"role_arn" cty:"role_arn"`
|
||||
TTL *string `mapstructure:"ttl" required:"false" cty:"ttl"`
|
||||
EngineName *string `mapstructure:"engine_name" cty:"engine_name"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatVaultAWSEngineOptions.
|
||||
|
||||
@@ -47,15 +47,15 @@ type AMIConfig struct {
|
||||
// Set to true if you want to skip
|
||||
// validation of the ami_regions configuration option. Default false.
|
||||
AMISkipRegionValidation bool `mapstructure:"skip_region_validation" required:"false"`
|
||||
// Key/value pair tags applied to the AMI. This is a [template
|
||||
// engine](/docs/templates/engine), see [Build template
|
||||
// Tags applied to the AMI. This is a
|
||||
// [template engine](/docs/templates/engine), see [Build template
|
||||
// data](#build-template-data) for more information.
|
||||
AMITags map[string]string `mapstructure:"tags" required:"false"`
|
||||
// Same as [`tags`](#tags) but defined as a singular repeatable block
|
||||
// containing a `key` and a `value` field. In HCL2 mode the
|
||||
// containing a `name` and a `value` field. In HCL2 mode the
|
||||
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
AMITag hcl2template.KeyValues `mapstructure:"tag" required:"false"`
|
||||
AMITag hcl2template.NameValues `mapstructure:"tag" required:"false"`
|
||||
// Enable enhanced networking (ENA but not SriovNetSupport) on
|
||||
// HVM-compatible AMIs. If set, add `ec2:ModifyInstanceAttribute` to your
|
||||
// AWS IAM policy.
|
||||
@@ -117,16 +117,16 @@ type AMIConfig struct {
|
||||
// the intermediary AMI into any regions provided in `ami_regions`, then
|
||||
// delete the intermediary AMI. Default `false`.
|
||||
AMISkipBuildRegion bool `mapstructure:"skip_save_build_region"`
|
||||
// Key/value pair tags to apply to snapshot. They will override AMI tags if
|
||||
// already applied to snapshot. This is a [template
|
||||
// engine](/docs/templates/engine), see [Build template
|
||||
// Tags to apply to snapshot.
|
||||
// They will override AMI tags if already applied to snapshot. This is a
|
||||
// [template engine](/docs/templates/engine), see [Build template
|
||||
// data](#build-template-data) for more information.
|
||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false"`
|
||||
// Same as [`snapshot_tags`](#snapshot_tags) but defined as a singular
|
||||
// repeatable block containing a `key` and a `value` field. In HCL2 mode the
|
||||
// repeatable block containing a `name` and a `value` field. In HCL2 mode the
|
||||
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
SnapshotTag hcl2template.KeyValues `mapstructure:"snapshot_tag" required:"false"`
|
||||
SnapshotTag hcl2template.NameValues `mapstructure:"snapshot_tag" required:"false"`
|
||||
// A list of account IDs that have
|
||||
// access to create volumes from the snapshot(s). By default no additional
|
||||
// users other than the user creating the AMI has permissions to create
|
||||
|
||||
@@ -21,26 +21,12 @@ import (
|
||||
// The following mapping will tell Packer to encrypt the root volume of the
|
||||
// build instance at launch using a specific non-default kms key:
|
||||
//
|
||||
// JSON example:
|
||||
//
|
||||
// ```json
|
||||
// ami_block_device_mappings: [
|
||||
// {
|
||||
// "device_name": "/dev/sda1",
|
||||
// "encrypted": true,
|
||||
// "kms_key_id": "1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d"
|
||||
// }
|
||||
// ]
|
||||
// ```
|
||||
//
|
||||
// HCL2 example:
|
||||
//
|
||||
// ```hcl
|
||||
// ami_block_device_mappings {
|
||||
// device_name = "/dev/sda1"
|
||||
// encrypted = true
|
||||
// kms_key_id = "1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d"
|
||||
// }
|
||||
// [{
|
||||
// "device_name": "/dev/sda1",
|
||||
// "encrypted": true,
|
||||
// "kms_key_id": "1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d"
|
||||
// }]
|
||||
// ```
|
||||
//
|
||||
// Documentation for Block Devices Mappings can be found here:
|
||||
|
||||
@@ -9,16 +9,16 @@ import (
|
||||
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatBlockDevice struct {
|
||||
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" hcl:"delete_on_termination"`
|
||||
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name" hcl:"device_name"`
|
||||
Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted" hcl:"encrypted"`
|
||||
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops" hcl:"iops"`
|
||||
NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device" hcl:"no_device"`
|
||||
SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id" hcl:"snapshot_id"`
|
||||
VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name" hcl:"virtual_name"`
|
||||
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type" hcl:"volume_type"`
|
||||
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size" hcl:"volume_size"`
|
||||
KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"`
|
||||
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination"`
|
||||
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name"`
|
||||
Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted"`
|
||||
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops"`
|
||||
NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device"`
|
||||
SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id"`
|
||||
VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name"`
|
||||
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type"`
|
||||
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size"`
|
||||
KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatBlockDevice.
|
||||
|
||||
@@ -31,7 +31,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error {
|
||||
err = retry.Config{
|
||||
Tries: 11,
|
||||
ShouldRetry: func(err error) bool {
|
||||
return IsAWSErr(err, "UnauthorizedOperation", "")
|
||||
return isAWSErr(err, "UnauthorizedOperation", "")
|
||||
},
|
||||
RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear,
|
||||
}.Run(ctx, func(ctx context.Context) error {
|
||||
@@ -54,7 +54,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error {
|
||||
err = retry.Config{
|
||||
Tries: 11,
|
||||
ShouldRetry: func(err error) bool {
|
||||
return IsAWSErr(err, "UnauthorizedOperation", "")
|
||||
return isAWSErr(err, "UnauthorizedOperation", "")
|
||||
},
|
||||
RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear,
|
||||
}.Run(ctx, func(ctx context.Context) error {
|
||||
@@ -79,7 +79,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error {
|
||||
// * err is of type awserr.Error
|
||||
// * Error.Code() matches code
|
||||
// * Error.Message() contains message
|
||||
func IsAWSErr(err error, code string, message string) bool {
|
||||
func isAWSErr(err error, code string, message string) bool {
|
||||
if err, ok := err.(awserr.Error); ok {
|
||||
return err.Code() == code && strings.Contains(err.Message(), message)
|
||||
}
|
||||
|
||||
@@ -8,13 +8,12 @@ import (
|
||||
)
|
||||
|
||||
type BuildInfoTemplate struct {
|
||||
BuildRegion string
|
||||
SourceAMI string
|
||||
SourceAMICreationDate string
|
||||
SourceAMIName string
|
||||
SourceAMIOwner string
|
||||
SourceAMIOwnerName string
|
||||
SourceAMITags map[string]string
|
||||
BuildRegion string
|
||||
SourceAMI string
|
||||
SourceAMIName string
|
||||
SourceAMIOwner string
|
||||
SourceAMIOwnerName string
|
||||
SourceAMITags map[string]string
|
||||
}
|
||||
|
||||
func extractBuildInfo(region string, state multistep.StateBag, generatedData *builder.GeneratedData) *BuildInfoTemplate {
|
||||
@@ -32,13 +31,12 @@ func extractBuildInfo(region string, state multistep.StateBag, generatedData *bu
|
||||
}
|
||||
|
||||
buildInfoTemplate := &BuildInfoTemplate{
|
||||
BuildRegion: region,
|
||||
SourceAMI: aws.StringValue(sourceAMI.ImageId),
|
||||
SourceAMICreationDate: aws.StringValue(sourceAMI.CreationDate),
|
||||
SourceAMIName: aws.StringValue(sourceAMI.Name),
|
||||
SourceAMIOwner: aws.StringValue(sourceAMI.OwnerId),
|
||||
SourceAMIOwnerName: aws.StringValue(sourceAMI.ImageOwnerAlias),
|
||||
SourceAMITags: sourceAMITags,
|
||||
BuildRegion: region,
|
||||
SourceAMI: aws.StringValue(sourceAMI.ImageId),
|
||||
SourceAMIName: aws.StringValue(sourceAMI.Name),
|
||||
SourceAMIOwner: aws.StringValue(sourceAMI.OwnerId),
|
||||
SourceAMIOwnerName: aws.StringValue(sourceAMI.ImageOwnerAlias),
|
||||
SourceAMITags: sourceAMITags,
|
||||
}
|
||||
generatedData.Put("SourceAMIName", buildInfoTemplate.SourceAMIName)
|
||||
return buildInfoTemplate
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
func testImage() *ec2.Image {
|
||||
return &ec2.Image{
|
||||
ImageId: aws.String("ami-abcd1234"),
|
||||
CreationDate: aws.String("ami_test_creation_date"),
|
||||
Name: aws.String("ami_test_name"),
|
||||
OwnerId: aws.String("ami_test_owner_id"),
|
||||
ImageOwnerAlias: aws.String("ami_test_owner_alias"),
|
||||
@@ -60,12 +59,11 @@ func TestInterpolateBuildInfo_extractBuildInfo_withSourceImage(t *testing.T) {
|
||||
buildInfo := extractBuildInfo("foo", state, &generatedData)
|
||||
|
||||
expected := BuildInfoTemplate{
|
||||
BuildRegion: "foo",
|
||||
SourceAMI: "ami-abcd1234",
|
||||
SourceAMICreationDate: "ami_test_creation_date",
|
||||
SourceAMIName: "ami_test_name",
|
||||
SourceAMIOwner: "ami_test_owner_id",
|
||||
SourceAMIOwnerName: "ami_test_owner_alias",
|
||||
BuildRegion: "foo",
|
||||
SourceAMI: "ami-abcd1234",
|
||||
SourceAMIName: "ami_test_name",
|
||||
SourceAMIOwner: "ami_test_owner_id",
|
||||
SourceAMIOwnerName: "ami_test_owner_alias",
|
||||
SourceAMITags: map[string]string{
|
||||
"key-1": "value-1",
|
||||
"key-2": "value-2",
|
||||
|
||||
@@ -20,9 +20,9 @@ import (
|
||||
var reShutdownBehavior = regexp.MustCompile("^(stop|terminate)$")
|
||||
|
||||
type AmiFilterOptions struct {
|
||||
hcl2template.KeyValueFilter `mapstructure:",squash"`
|
||||
Owners []string
|
||||
MostRecent bool `mapstructure:"most_recent"`
|
||||
hcl2template.KVFilter `mapstructure:",squash"`
|
||||
Owners []string
|
||||
MostRecent bool `mapstructure:"most_recent"`
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) GetOwners() []*string {
|
||||
@@ -35,7 +35,7 @@ func (d *AmiFilterOptions) GetOwners() []*string {
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) Empty() bool {
|
||||
return len(d.Owners) == 0 && d.KeyValueFilter.Empty()
|
||||
return len(d.Owners) == 0 && d.KVFilter.Empty()
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) NoOwner() bool {
|
||||
@@ -43,19 +43,19 @@ func (d *AmiFilterOptions) NoOwner() bool {
|
||||
}
|
||||
|
||||
type SubnetFilterOptions struct {
|
||||
hcl2template.NameValueFilter `mapstructure:",squash"`
|
||||
MostFree bool `mapstructure:"most_free"`
|
||||
Random bool `mapstructure:"random"`
|
||||
hcl2template.KVFilter `mapstructure:",squash"`
|
||||
MostFree bool `mapstructure:"most_free"`
|
||||
Random bool `mapstructure:"random"`
|
||||
}
|
||||
|
||||
type VpcFilterOptions struct {
|
||||
hcl2template.NameValueFilter `mapstructure:",squash"`
|
||||
hcl2template.KVFilter `mapstructure:",squash"`
|
||||
}
|
||||
|
||||
type Statement struct {
|
||||
Effect string
|
||||
Action []string
|
||||
Resource []string
|
||||
Resource string
|
||||
}
|
||||
|
||||
type PolicyDocument struct {
|
||||
@@ -64,7 +64,7 @@ type PolicyDocument struct {
|
||||
}
|
||||
|
||||
type SecurityGroupFilterOptions struct {
|
||||
hcl2template.NameValueFilter `mapstructure:",squash"`
|
||||
hcl2template.KVFilter `mapstructure:",squash"`
|
||||
}
|
||||
|
||||
// RunConfig contains configuration for running an instance from a source
|
||||
@@ -89,23 +89,19 @@ type RunConfig struct {
|
||||
// which will stop the instance for you. If this is set to `true`, Packer
|
||||
// *will not* stop the instance but will assume that you will send the stop
|
||||
// signal yourself through your final provisioner. You can do this with a
|
||||
// [windows-shell provisioner](/docs/provisioners/windows-shell). Note that
|
||||
// Packer will still wait for the instance to be stopped, and failing to
|
||||
// send the stop signal yourself, when you have set this flag to `true`,
|
||||
// will cause a timeout.
|
||||
// [windows-shell
|
||||
// provisioner](/docs/provisioners/windows-shell).
|
||||
// Note that Packer will still wait for the instance to be stopped, and
|
||||
// failing to send the stop signal yourself, when you have set this flag to
|
||||
// `true`, will cause a timeout.
|
||||
// Example of a valid shutdown command:
|
||||
//
|
||||
// An example of a valid windows shutdown command in a `windows-shell`
|
||||
// provisioner is :
|
||||
// ```shell-session
|
||||
// ec2config.exe -sysprep
|
||||
// ```json
|
||||
// {
|
||||
// "type": "windows-shell",
|
||||
// "inline": ["\"c:\\Program Files\\Amazon\\Ec2ConfigService\\ec2config.exe\" -sysprep"]
|
||||
// }
|
||||
// ```
|
||||
// or
|
||||
// ```sell-session
|
||||
// "%programfiles%\amazon\ec2configservice\"ec2config.exe -sysprep""
|
||||
// ```
|
||||
// -> Note: The double quotation marks in the command are not required if
|
||||
// your CMD shell is already in the
|
||||
// `C:\Program Files\Amazon\EC2ConfigService\` directory.
|
||||
DisableStopInstance bool `mapstructure:"disable_stop_instance" required:"false"`
|
||||
// Mark instance as [EBS
|
||||
// Optimized](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html).
|
||||
@@ -166,7 +162,7 @@ type RunConfig struct {
|
||||
// The EC2 instance type to use while building the
|
||||
// AMI, such as t2.small.
|
||||
InstanceType string `mapstructure:"instance_type" required:"true"`
|
||||
// Filters used to populate the `security_group_ids` field. JSON Example:
|
||||
// Filters used to populate the `security_group_ids` field. Example:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
@@ -178,16 +174,6 @@ type RunConfig struct {
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// HCL2 Example:
|
||||
//
|
||||
// ```hcl
|
||||
// security_group_filter {
|
||||
// filters = {
|
||||
// "tag:Class": "packer"
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// This selects the SG's with tag `Class` with the value `packer`.
|
||||
//
|
||||
// - `filters` (map of strings) - filters used to select a
|
||||
@@ -197,16 +183,15 @@ type RunConfig struct {
|
||||
//
|
||||
// `security_group_ids` take precedence over this.
|
||||
SecurityGroupFilter SecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false"`
|
||||
// Key/value pair tags to apply to the instance that is that is *launched*
|
||||
// to create the EBS volumes. This is a [template
|
||||
// engine](/docs/templates/engine), see [Build template
|
||||
// data](#build-template-data) for more information.
|
||||
// Tags to apply to the instance that is that is *launched* to create the
|
||||
// EBS volumes. This is a [template engine](/docs/templates/engine),
|
||||
// see [Build template data](#build-template-data) for more information.
|
||||
RunTags map[string]string `mapstructure:"run_tags" required:"false"`
|
||||
// Same as [`run_tags`](#run_tags) but defined as a singular repeatable
|
||||
// block containing a `key` and a `value` field. In HCL2 mode the
|
||||
// block containing a `name` and a `value` field. In HCL2 mode the
|
||||
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
RunTag hcl2template.KeyValues `mapstructure:"run_tag" required:"false"`
|
||||
RunTag hcl2template.NameValues `mapstructure:"run_tag" required:"false"`
|
||||
// The ID (not the name) of the security
|
||||
// group to assign to the instance. By default this is not set and Packer will
|
||||
// automatically create a new temporary security group to allow SSH access.
|
||||
@@ -223,39 +208,21 @@ type RunConfig struct {
|
||||
// used when from_scratch is set to true.
|
||||
SourceAmi string `mapstructure:"source_ami" required:"true"`
|
||||
// Filters used to populate the `source_ami`
|
||||
// field. JSON Example:
|
||||
// field. Example:
|
||||
//
|
||||
// ```json
|
||||
// "builders" [
|
||||
// ```json
|
||||
// {
|
||||
// "type": "amazon-ebs",
|
||||
// "source_ami_filter": {
|
||||
// "filters": {
|
||||
// "virtualization-type": "hvm",
|
||||
// "name": "ubuntu/images/\*ubuntu-xenial-16.04-amd64-server-\*",
|
||||
// "root-device-type": "ebs"
|
||||
// },
|
||||
// "owners": ["099720109477"],
|
||||
// "most_recent": true
|
||||
// "filters": {
|
||||
// "virtualization-type": "hvm",
|
||||
// "name": "ubuntu/images/\*ubuntu-xenial-16.04-amd64-server-\*",
|
||||
// "root-device-type": "ebs"
|
||||
// },
|
||||
// "owners": ["099720109477"],
|
||||
// "most_recent": true
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// ```
|
||||
// HCL2 example:
|
||||
//
|
||||
// ```hcl
|
||||
// source "amazon-ebs" "basic-example" {
|
||||
// source_ami_filter {
|
||||
// filters = {
|
||||
// virtualization-type = "hvm"
|
||||
// name = "ubuntu/images/\*ubuntu-xenial-16.04-amd64-server-\*"
|
||||
// root-device-type = "ebs"
|
||||
// }
|
||||
// owners = ["099720109477"]
|
||||
// most_recent = true
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
// ```
|
||||
//
|
||||
// This selects the most recent Ubuntu 16.04 HVM EBS AMI from Canonical. NOTE:
|
||||
// This will fail unless *exactly* one AMI is returned. In the above example,
|
||||
@@ -313,22 +280,20 @@ type RunConfig struct {
|
||||
// best spot price. This must be one of: Linux/UNIX, SUSE Linux,
|
||||
// Windows, Linux/UNIX (Amazon VPC), SUSE Linux (Amazon VPC),
|
||||
// Windows (Amazon VPC)
|
||||
SpotPriceAutoProduct string `mapstructure:"spot_price_auto_product" required:"false" undocumented:"true"`
|
||||
// Requires spot_price to be set. Key/value pair tags to apply tags to the
|
||||
SpotPriceAutoProduct string `mapstructure:"spot_price_auto_product" required:"false"`
|
||||
// Requires spot_price to be set. This tells Packer to apply tags to the
|
||||
// spot request that is issued.
|
||||
SpotTags map[string]string `mapstructure:"spot_tags" required:"false"`
|
||||
// Same as [`spot_tags`](#spot_tags) but defined as a singular repeatable block
|
||||
// containing a `key` and a `value` field. In HCL2 mode the
|
||||
// containing a `name` and a `value` field. In HCL2 mode the
|
||||
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
SpotTag hcl2template.KeyValues `mapstructure:"spot_tag" required:"false"`
|
||||
SpotTag hcl2template.NameValues `mapstructure:"spot_tag" required:"false"`
|
||||
// Filters used to populate the `subnet_id` field.
|
||||
// JSON Example:
|
||||
// Example:
|
||||
//
|
||||
// ```json
|
||||
// "builders" [
|
||||
// ```json
|
||||
// {
|
||||
// "type": "amazon-ebs",
|
||||
// "subnet_filter": {
|
||||
// "filters": {
|
||||
// "tag:Class": "build"
|
||||
@@ -337,21 +302,7 @@ type RunConfig struct {
|
||||
// "random": false
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// ```
|
||||
// HCL2 example:
|
||||
//
|
||||
// ```hcl
|
||||
// source "amazon-ebs" "basic-example" {
|
||||
// subnet_filter {
|
||||
// filters = {
|
||||
// "tag:Class": "build"
|
||||
// }
|
||||
// most_free = true
|
||||
// random = false
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
// ```
|
||||
//
|
||||
// This selects the Subnet with tag `Class` with the value `build`, which has
|
||||
// the most free IP addresses. NOTE: This will fail unless *exactly* one
|
||||
@@ -396,28 +347,12 @@ type RunConfig struct {
|
||||
// data when launching the instance.
|
||||
UserDataFile string `mapstructure:"user_data_file" required:"false"`
|
||||
// Filters used to populate the `vpc_id` field.
|
||||
// JSON Example:
|
||||
// Example:
|
||||
//
|
||||
// ```json
|
||||
// "builders" [
|
||||
// {
|
||||
// "type": "amazon-ebs",
|
||||
// "vpc_filter": {
|
||||
// "filters": {
|
||||
// "tag:Class": "build",
|
||||
// "isDefault": "false",
|
||||
// "cidr": "/24"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// ```
|
||||
// HCL2 example:
|
||||
//
|
||||
// ```hcl
|
||||
// source "amazon-ebs" "basic-example" {
|
||||
// vpc_filter {
|
||||
// filters = {
|
||||
// {
|
||||
// "vpc_filter": {
|
||||
// "filters": {
|
||||
// "tag:Class": "build",
|
||||
// "isDefault": "false",
|
||||
// "cidr": "/24"
|
||||
@@ -451,8 +386,8 @@ type RunConfig struct {
|
||||
// Communicator settings
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
|
||||
// One of `public_ip`, `private_ip`, `public_dns`, `private_dns` or `session_manager`.
|
||||
// If set, either the public IP address, private IP address, public DNS name
|
||||
// One of `public_ip`, `private_ip`, `public_dns`, or `private_dns`. If
|
||||
// set, either the public IP address, private IP address, public DNS name
|
||||
// or private DNS name will be used as the host for SSH. The default behaviour
|
||||
// if inside a VPC is to use the public IP address if available, otherwise
|
||||
// the private IP address will be used. If not in a VPC the public DNS name
|
||||
@@ -462,21 +397,7 @@ type RunConfig struct {
|
||||
// should be direct, `ssh_interface` must be set to `private_dns` and
|
||||
// `<region>.compute.internal` included in the `NO_PROXY` environment
|
||||
// variable.
|
||||
//
|
||||
// When using `session_manager` the machine running Packer must have
|
||||
// the AWS Session Manager Plugin installed and within the users' system path.
|
||||
// Connectivity via the `session_manager` interface establishes a secure tunnel
|
||||
// between the local host and the remote host on an available local port to the specified `ssh_port`.
|
||||
// See [Session Manager Connections](#session-manager-connections) for more information.
|
||||
// - Session manager connectivity is currently only implemented for the SSH communicator, not the WinRM communicator.
|
||||
// - Upon termination the secure tunnel will be terminated automatically, if however there is a failure in
|
||||
// terminating the tunnel it will automatically terminate itself after 20 minutes of inactivity.
|
||||
SSHInterface string `mapstructure:"ssh_interface"`
|
||||
|
||||
// Which port to connect the local end of the session tunnel to. If
|
||||
// left blank, Packer will choose a port for you from available ports.
|
||||
// This option is only used when `ssh_interface` is set `session_manager`.
|
||||
SessionManagerPort int `mapstructure:"session_manager_port"`
|
||||
}
|
||||
|
||||
func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
@@ -519,24 +440,10 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
c.SSHInterface != "private_ip" &&
|
||||
c.SSHInterface != "public_dns" &&
|
||||
c.SSHInterface != "private_dns" &&
|
||||
c.SSHInterface != "session_manager" &&
|
||||
c.SSHInterface != "" {
|
||||
errs = append(errs, fmt.Errorf("Unknown interface type: %s", c.SSHInterface))
|
||||
}
|
||||
|
||||
// Connectivity via Session Manager has a few requirements
|
||||
if c.SSHInterface == "session_manager" {
|
||||
if c.Comm.Type == "winrm" {
|
||||
msg := fmt.Errorf(`session_manager connectivity is not supported with the "winrm" communicator; please use "ssh"`)
|
||||
errs = append(errs, msg)
|
||||
}
|
||||
|
||||
if c.IamInstanceProfile == "" && c.TemporaryIamInstanceProfilePolicyDocument == nil {
|
||||
msg := fmt.Errorf(`no iam_instance_profile defined; session_manager connectivity requires a valid instance profile with AmazonSSMManagedInstanceCore permissions. Alternatively a temporary_iam_instance_profile_policy_document can be used.`)
|
||||
errs = append(errs, msg)
|
||||
}
|
||||
}
|
||||
|
||||
if c.Comm.SSHKeyPairName != "" {
|
||||
if c.Comm.Type == "winrm" && c.Comm.WinRMPassword == "" && c.Comm.SSHPrivateKeyFile == "" {
|
||||
errs = append(errs, fmt.Errorf("ssh_private_key_file must be provided to retrieve the winrm password when using ssh_keypair_name."))
|
||||
@@ -610,7 +517,7 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
|
||||
if c.EnableT2Unlimited {
|
||||
if c.SpotPrice != "" {
|
||||
errs = append(errs, fmt.Errorf("Error: T2 Unlimited cannot be used in conjunction with Spot Instances"))
|
||||
errs = append(errs, fmt.Errorf("Error: T2 Unlimited cannot be used in conjuction with Spot Instances"))
|
||||
}
|
||||
firstDotIndex := strings.Index(c.InstanceType, ".")
|
||||
if firstDotIndex == -1 {
|
||||
@@ -626,8 +533,3 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
func (c *RunConfig) IsSpotInstance() bool {
|
||||
return c.SpotPrice != "" && c.SpotPrice != "0"
|
||||
}
|
||||
|
||||
func (c *RunConfig) SSMAgentEnabled() bool {
|
||||
hasIamInstanceProfile := c.IamInstanceProfile != "" || c.TemporaryIamInstanceProfilePolicyDocument != nil
|
||||
return c.SSHInterface == "session_manager" && hasIamInstanceProfile
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
// FlatAmiFilterOptions is an auto-generated flat version of AmiFilterOptions.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatAmiFilterOptions struct {
|
||||
Filters map[string]string `cty:"filters" hcl:"filters"`
|
||||
Filter []hcl2template.FlatKeyValue `cty:"filter" hcl:"filter"`
|
||||
Owners []string `cty:"owners" hcl:"owners"`
|
||||
MostRecent *bool `mapstructure:"most_recent" cty:"most_recent" hcl:"most_recent"`
|
||||
Filters map[string]string `cty:"filters"`
|
||||
Filter []hcl2template.FlatNameValue `cty:"filter"`
|
||||
Owners []string `cty:"owners"`
|
||||
MostRecent *bool `mapstructure:"most_recent" cty:"most_recent"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatAmiFilterOptions.
|
||||
@@ -29,7 +29,7 @@ func (*AmiFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcl
|
||||
func (*FlatAmiFilterOptions) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
|
||||
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
}
|
||||
@@ -39,8 +39,8 @@ func (*FlatAmiFilterOptions) HCL2Spec() map[string]hcldec.Spec {
|
||||
// FlatPolicyDocument is an auto-generated flat version of PolicyDocument.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatPolicyDocument struct {
|
||||
Version *string `cty:"version" hcl:"version"`
|
||||
Statement []FlatStatement `cty:"statement" hcl:"statement"`
|
||||
Version *string `cty:"version"`
|
||||
Statement []FlatStatement `cty:"statement"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatPolicyDocument.
|
||||
@@ -64,8 +64,8 @@ func (*FlatPolicyDocument) HCL2Spec() map[string]hcldec.Spec {
|
||||
// FlatSecurityGroupFilterOptions is an auto-generated flat version of SecurityGroupFilterOptions.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatSecurityGroupFilterOptions struct {
|
||||
Filters map[string]string `cty:"filters" hcl:"filters"`
|
||||
Filter []hcl2template.FlatNameValue `cty:"filter" hcl:"filter"`
|
||||
Filters map[string]string `cty:"filters"`
|
||||
Filter []hcl2template.FlatNameValue `cty:"filter"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatSecurityGroupFilterOptions.
|
||||
@@ -89,9 +89,9 @@ func (*FlatSecurityGroupFilterOptions) HCL2Spec() map[string]hcldec.Spec {
|
||||
// FlatStatement is an auto-generated flat version of Statement.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatStatement struct {
|
||||
Effect *string `cty:"effect" hcl:"effect"`
|
||||
Action []string `cty:"action" hcl:"action"`
|
||||
Resource []string `cty:"resource" hcl:"resource"`
|
||||
Effect *string `cty:"effect"`
|
||||
Action []string `cty:"action"`
|
||||
Resource *string `cty:"resource"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatStatement.
|
||||
@@ -108,7 +108,7 @@ func (*FlatStatement) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"effect": &hcldec.AttrSpec{Name: "effect", Type: cty.String, Required: false},
|
||||
"action": &hcldec.AttrSpec{Name: "action", Type: cty.List(cty.String), Required: false},
|
||||
"resource": &hcldec.AttrSpec{Name: "resource", Type: cty.List(cty.String), Required: false},
|
||||
"resource": &hcldec.AttrSpec{Name: "resource", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -116,10 +116,10 @@ func (*FlatStatement) HCL2Spec() map[string]hcldec.Spec {
|
||||
// FlatSubnetFilterOptions is an auto-generated flat version of SubnetFilterOptions.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatSubnetFilterOptions struct {
|
||||
Filters map[string]string `cty:"filters" hcl:"filters"`
|
||||
Filter []hcl2template.FlatNameValue `cty:"filter" hcl:"filter"`
|
||||
MostFree *bool `mapstructure:"most_free" cty:"most_free" hcl:"most_free"`
|
||||
Random *bool `mapstructure:"random" cty:"random" hcl:"random"`
|
||||
Filters map[string]string `cty:"filters"`
|
||||
Filter []hcl2template.FlatNameValue `cty:"filter"`
|
||||
MostFree *bool `mapstructure:"most_free" cty:"most_free"`
|
||||
Random *bool `mapstructure:"random" cty:"random"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatSubnetFilterOptions.
|
||||
@@ -145,8 +145,8 @@ func (*FlatSubnetFilterOptions) HCL2Spec() map[string]hcldec.Spec {
|
||||
// FlatVpcFilterOptions is an auto-generated flat version of VpcFilterOptions.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatVpcFilterOptions struct {
|
||||
Filters map[string]string `cty:"filters" hcl:"filters"`
|
||||
Filter []hcl2template.FlatNameValue `cty:"filter" hcl:"filter"`
|
||||
Filters map[string]string `cty:"filters"`
|
||||
Filter []hcl2template.FlatNameValue `cty:"filter"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatVpcFilterOptions.
|
||||
|
||||
@@ -87,7 +87,7 @@ func TestRunConfigPrepare_SourceAmiFilterGood(t *testing.T) {
|
||||
filter_value := "foo"
|
||||
goodFilter := AmiFilterOptions{
|
||||
Owners: []string{owner},
|
||||
KeyValueFilter: hcl2template.KeyValueFilter{
|
||||
KVFilter: hcl2template.KVFilter{
|
||||
Filters: map[string]string{filter_key: filter_value},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -28,10 +28,6 @@ func SSHHost(e ec2Describer, sshInterface string, host string) func(multistep.St
|
||||
return host, nil
|
||||
}
|
||||
|
||||
if sshInterface == "session_manager" {
|
||||
return "localhost", nil
|
||||
}
|
||||
|
||||
const tries = 2
|
||||
// <= with current structure to check result of describing `tries` times
|
||||
for j := 0; j <= tries; j++ {
|
||||
@@ -89,20 +85,3 @@ func SSHHost(e ec2Describer, sshInterface string, host string) func(multistep.St
|
||||
return "", errors.New("couldn't determine address for instance")
|
||||
}
|
||||
}
|
||||
|
||||
// Port returns a function that can be given to the communicator
|
||||
// for determining the port to use when connecting to an instance.
|
||||
func Port(sshInterface string, port int) func(multistep.StateBag) (int, error) {
|
||||
return func(state multistep.StateBag) (int, error) {
|
||||
if sshInterface != "session_manager" {
|
||||
return port, nil
|
||||
}
|
||||
|
||||
port, ok := state.GetOk("sessionPort")
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("no local port defined for session-manager")
|
||||
}
|
||||
return port.(int), nil
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ const (
|
||||
publicIP = "192.168.1.1"
|
||||
privateDNS = "private.dns.test"
|
||||
publicDNS = "public.dns.test"
|
||||
localhost = "localhost"
|
||||
sshHostTemplate = "custom.host.value"
|
||||
)
|
||||
|
||||
@@ -33,13 +32,11 @@ func TestSSHHost(t *testing.T) {
|
||||
}{
|
||||
{1, "", "", true, publicDNS, ""},
|
||||
{1, "", "private_ip", true, privateIP, ""},
|
||||
{1, "", "session_manager", true, localhost, ""},
|
||||
{1, "vpc-id", "", true, publicIP, ""},
|
||||
{1, "vpc-id", "private_ip", true, privateIP, ""},
|
||||
{1, "vpc-id", "private_dns", true, privateDNS, ""},
|
||||
{1, "vpc-id", "public_dns", true, publicDNS, ""},
|
||||
{1, "vpc-id", "public_ip", true, publicIP, ""},
|
||||
{1, "vpc-id", "session_manager", true, localhost, ""},
|
||||
{2, "", "", true, publicDNS, ""},
|
||||
{2, "", "private_ip", true, privateIP, ""},
|
||||
{2, "vpc-id", "", true, publicIP, ""},
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/aws/aws-sdk-go/service/ssm/ssmiface"
|
||||
"github.com/hashicorp/packer/common/retry"
|
||||
"github.com/mitchellh/iochan"
|
||||
)
|
||||
|
||||
const (
|
||||
sessionManagerPluginName string = "session-manager-plugin"
|
||||
|
||||
//sessionCommand is the AWS-SDK equivalent to the command you would specify to `aws ssm ...`
|
||||
sessionCommand string = "StartSession"
|
||||
)
|
||||
|
||||
type SSMDriverConfig struct {
|
||||
SvcClient ssmiface.SSMAPI
|
||||
Region string
|
||||
ProfileName string
|
||||
SvcEndpoint string
|
||||
}
|
||||
|
||||
type SSMDriver struct {
|
||||
SSMDriverConfig
|
||||
session *ssm.StartSessionOutput
|
||||
sessionParams ssm.StartSessionInput
|
||||
pluginCmdFunc func(context.Context) error
|
||||
}
|
||||
|
||||
func NewSSMDriver(config SSMDriverConfig) *SSMDriver {
|
||||
d := SSMDriver{SSMDriverConfig: config}
|
||||
return &d
|
||||
}
|
||||
|
||||
// StartSession starts an interactive Systems Manager session with a remote instance via the AWS session-manager-plugin
|
||||
// This ssm.StartSessionOutput returned by this function can be used for terminating the session manually. If you do
|
||||
// not wish to manage the session manually calling StopSession on a instance of this driver will terminate the active session
|
||||
// created from calling StartSession.
|
||||
func (d *SSMDriver) StartSession(ctx context.Context, input ssm.StartSessionInput) (*ssm.StartSessionOutput, error) {
|
||||
log.Printf("Starting PortForwarding session to instance %q with following params %v", aws.StringValue(input.Target), input.Parameters)
|
||||
|
||||
var output *ssm.StartSessionOutput
|
||||
err := retry.Config{
|
||||
ShouldRetry: func(err error) bool { return IsAWSErr(err, "TargetNotConnected", "") },
|
||||
RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 60 * time.Second, Multiplier: 2}).Linear,
|
||||
}.Run(ctx, func(ctx context.Context) (err error) {
|
||||
output, err = d.SvcClient.StartSessionWithContext(ctx, &input)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encountered in starting session for instance %q: %s", aws.StringValue(input.Target), err)
|
||||
}
|
||||
|
||||
d.session = output
|
||||
d.sessionParams = input
|
||||
|
||||
if d.pluginCmdFunc == nil {
|
||||
d.pluginCmdFunc = d.openTunnelForSession
|
||||
}
|
||||
|
||||
if err := d.pluginCmdFunc(ctx); err != nil {
|
||||
return nil, fmt.Errorf("error encountered in starting session for instance %q: %s", aws.StringValue(input.Target), err)
|
||||
}
|
||||
|
||||
return d.session, nil
|
||||
}
|
||||
|
||||
func (d *SSMDriver) openTunnelForSession(ctx context.Context) error {
|
||||
args, err := d.Args()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error encountered validating session details: %s", err)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, sessionManagerPluginName, args...)
|
||||
|
||||
// Let's build up our logging
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create the channels we'll use for data
|
||||
stdoutCh := iochan.DelimReader(stdout, '\n')
|
||||
stderrCh := iochan.DelimReader(stderr, '\n')
|
||||
|
||||
/* Loop and get all our output
|
||||
This particular logger will continue to run through an entire Packer run.
|
||||
The decision to continue logging is due to the fact that session-manager-plugin
|
||||
doesn't give a good way of knowing if the command failed or was successful other
|
||||
than looking at the logs. Seeing as the plugin is updated frequently and that the
|
||||
log information is a bit sparse this logger will indefinitely relying on other
|
||||
steps to fail if the tunnel is unable to be created. If successful then the user
|
||||
will get more information on the tunnel connection when running in a debug mode.
|
||||
*/
|
||||
go func(ctx context.Context, prefix string) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case output := <-stderrCh:
|
||||
if output != "" {
|
||||
log.Printf("[ERROR] %s: %s", prefix, output)
|
||||
}
|
||||
case output := <-stdoutCh:
|
||||
if output != "" {
|
||||
log.Printf("[DEBUG] %s: %s", prefix, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}(ctx, sessionManagerPluginName)
|
||||
|
||||
log.Printf("[DEBUG %s] opening session tunnel to instance %q for session %q", sessionManagerPluginName,
|
||||
aws.StringValue(d.sessionParams.Target),
|
||||
aws.StringValue(d.session.SessionId),
|
||||
)
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
err = fmt.Errorf("error encountered when calling %s: %s\n", sessionManagerPluginName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopSession terminates an active Session Manager session
|
||||
func (d *SSMDriver) StopSession() error {
|
||||
|
||||
if d.session == nil || d.session.SessionId == nil {
|
||||
return fmt.Errorf("Unable to find a valid session to instance %q; skipping the termination step",
|
||||
aws.StringValue(d.sessionParams.Target))
|
||||
}
|
||||
|
||||
_, err := d.SvcClient.TerminateSession(&ssm.TerminateSessionInput{SessionId: d.session.SessionId})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error terminating SSM Session %q. Please terminate the session manually: %s", aws.StringValue(d.session.SessionId), err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Args validates the driver inputs before returning an ordered set of arguments to pass to the driver command.
|
||||
func (d *SSMDriver) Args() ([]string, error) {
|
||||
if d.session == nil {
|
||||
return nil, fmt.Errorf("an active Amazon SSM Session is required before trying to open a session tunnel")
|
||||
}
|
||||
|
||||
// AWS session-manager-plugin requires a valid session be passed in JSON.
|
||||
sessionDetails, err := json.Marshal(d.session)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encountered in reading session details %s", err)
|
||||
}
|
||||
|
||||
// AWS session-manager-plugin requires the parameters used in the session to be passed in JSON as well.
|
||||
sessionParameters, err := json.Marshal(d.sessionParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encountered in reading session parameter details %s", err)
|
||||
}
|
||||
|
||||
// Args must be in this order
|
||||
args := []string{
|
||||
string(sessionDetails),
|
||||
d.Region,
|
||||
sessionCommand,
|
||||
d.ProfileName,
|
||||
string(sessionParameters),
|
||||
d.SvcEndpoint,
|
||||
}
|
||||
|
||||
return args, nil
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func NewSSMDriverWithMockSvc(svc *MockSSMSvc) *SSMDriver {
|
||||
config := SSMDriverConfig{
|
||||
SvcClient: svc,
|
||||
Region: "east",
|
||||
ProfileName: "default",
|
||||
SvcEndpoint: "example.com",
|
||||
}
|
||||
|
||||
driver := SSMDriver{
|
||||
SSMDriverConfig: config,
|
||||
pluginCmdFunc: func(ctx context.Context) error { return nil },
|
||||
}
|
||||
|
||||
return &driver
|
||||
}
|
||||
func TestSSMDriver_StartSession(t *testing.T) {
|
||||
mockSvc := MockSSMSvc{}
|
||||
driver := NewSSMDriverWithMockSvc(&mockSvc)
|
||||
|
||||
if driver.SvcClient == nil {
|
||||
t.Fatalf("SvcClient for driver should not be nil")
|
||||
}
|
||||
|
||||
session, err := driver.StartSession(context.TODO(), MockStartSessionInput("fakeinstance"))
|
||||
if err != nil {
|
||||
t.Fatalf("calling StartSession should not error but got %v", err)
|
||||
}
|
||||
|
||||
if !mockSvc.StartSessionCalled {
|
||||
t.Fatalf("expected test to call ssm mocks but didn't")
|
||||
}
|
||||
|
||||
if session == nil {
|
||||
t.Errorf("expected session to be set after a successful call to StartSession")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(session, MockStartSessionOutput()) {
|
||||
t.Errorf("expected session to be %v but got %v", MockStartSessionOutput(), session)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSMDriver_StartSessionWithError(t *testing.T) {
|
||||
mockSvc := MockSSMSvc{StartSessionError: fmt.Errorf("bogus error")}
|
||||
driver := NewSSMDriverWithMockSvc(&mockSvc)
|
||||
|
||||
if driver.SvcClient == nil {
|
||||
t.Fatalf("SvcClient for driver should not be nil")
|
||||
}
|
||||
|
||||
session, err := driver.StartSession(context.TODO(), MockStartSessionInput("fakeinstance"))
|
||||
if err == nil {
|
||||
t.Fatalf("StartSession should have thrown an error but didn't")
|
||||
}
|
||||
|
||||
if !mockSvc.StartSessionCalled {
|
||||
t.Errorf("expected test to call StartSession mock but didn't")
|
||||
}
|
||||
|
||||
if session != nil {
|
||||
t.Errorf("expected session to be nil after a bad StartSession call, but got %v", session)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSMDriver_StopSession(t *testing.T) {
|
||||
mockSvc := MockSSMSvc{}
|
||||
driver := NewSSMDriverWithMockSvc(&mockSvc)
|
||||
|
||||
if driver.SvcClient == nil {
|
||||
t.Fatalf("SvcClient for driver should not be nil")
|
||||
}
|
||||
|
||||
// Calling StopSession before StartSession should fail
|
||||
err := driver.StopSession()
|
||||
if err == nil {
|
||||
t.Fatalf("calling StopSession() on a driver that has no started session should fail")
|
||||
}
|
||||
|
||||
if driver.session != nil {
|
||||
t.Errorf("expected session to be default to nil")
|
||||
}
|
||||
|
||||
if mockSvc.TerminateSessionCalled {
|
||||
t.Fatalf("a call to TerminateSession should not occur when there is no valid SSM session")
|
||||
}
|
||||
|
||||
// Lets try calling start session, then stopping to see what happens.
|
||||
session, err := driver.StartSession(context.TODO(), MockStartSessionInput("fakeinstance"))
|
||||
if err != nil {
|
||||
t.Fatalf("calling StartSession should not error but got %v", err)
|
||||
}
|
||||
|
||||
if !mockSvc.StartSessionCalled {
|
||||
t.Fatalf("expected test to call StartSession mock but didn't")
|
||||
}
|
||||
|
||||
if session == nil || driver.session != session {
|
||||
t.Errorf("expected session to be set after a successful call to StartSession")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(session, MockStartSessionOutput()) {
|
||||
t.Errorf("expected session to be %v but got %v", MockStartSessionOutput(), session)
|
||||
}
|
||||
|
||||
err = driver.StopSession()
|
||||
if err != nil {
|
||||
t.Errorf("calling StopSession() on a driver on a started session should not fail")
|
||||
}
|
||||
|
||||
if !mockSvc.TerminateSessionCalled {
|
||||
t.Fatalf("expected test to call StopSession mock but didn't")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSSMDriver_Args(t *testing.T) {
|
||||
tt := []struct {
|
||||
Name string
|
||||
ProfileName string
|
||||
SkipStartSession bool
|
||||
ErrorExpected bool
|
||||
}{
|
||||
{
|
||||
Name: "NilSession",
|
||||
SkipStartSession: true,
|
||||
ErrorExpected: true,
|
||||
},
|
||||
{
|
||||
Name: "NonNilSession",
|
||||
ErrorExpected: false,
|
||||
},
|
||||
{
|
||||
Name: "SessionWithProfileName",
|
||||
ProfileName: "default",
|
||||
ErrorExpected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
mockSvc := MockSSMSvc{}
|
||||
driver := NewSSMDriverWithMockSvc(&mockSvc)
|
||||
driver.ProfileName = tc.ProfileName
|
||||
|
||||
if driver.SvcClient == nil {
|
||||
t.Fatalf("svcclient for driver should not be nil")
|
||||
}
|
||||
|
||||
if !tc.SkipStartSession {
|
||||
_, err := driver.StartSession(context.TODO(), MockStartSessionInput("fakeinstance"))
|
||||
if err != nil {
|
||||
t.Fatalf("got an error when calling StartSession %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
args, err := driver.Args()
|
||||
if tc.ErrorExpected && err == nil {
|
||||
t.Fatalf("Driver.Args with a %q should have failed but instead no error was returned", tc.Name)
|
||||
}
|
||||
|
||||
if tc.ErrorExpected {
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("got an error when it should've worked %v", err)
|
||||
}
|
||||
|
||||
// validate launch script
|
||||
expectedArgString := fmt.Sprintf(`{"SessionId":"packerid","StreamUrl":"http://packer.io","TokenValue":"packer-token"} east StartSession %s {"DocumentName":"AWS-StartPortForwardingSession","Parameters":{"localPortNumber":["8001"],"portNumber":["22"]},"Target":"fakeinstance"} example.com`, tc.ProfileName)
|
||||
argString := strings.Join(args, " ")
|
||||
if argString != expectedArgString {
|
||||
t.Errorf("Expected launch script to be %q but got %q", expectedArgString, argString)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/aws/aws-sdk-go/service/ssm/ssmiface"
|
||||
)
|
||||
|
||||
type MockSSMSvc struct {
|
||||
ssmiface.SSMAPI
|
||||
StartSessionError error
|
||||
TerminateSessionError error
|
||||
StartSessionCalled bool
|
||||
TerminateSessionCalled bool
|
||||
}
|
||||
|
||||
func (svc *MockSSMSvc) StartSessionWithContext(ctx aws.Context, input *ssm.StartSessionInput, options ...request.Option) (*ssm.StartSessionOutput, error) {
|
||||
svc.StartSessionCalled = true
|
||||
return MockStartSessionOutput(), svc.StartSessionError
|
||||
}
|
||||
func (svc *MockSSMSvc) TerminateSession(input *ssm.TerminateSessionInput) (*ssm.TerminateSessionOutput, error) {
|
||||
svc.TerminateSessionCalled = true
|
||||
return new(ssm.TerminateSessionOutput), svc.TerminateSessionError
|
||||
}
|
||||
|
||||
func MockPluginCmdFunc(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func MockStartSessionOutput() *ssm.StartSessionOutput {
|
||||
id, url, token := "packerid", "http://packer.io", "packer-token"
|
||||
output := ssm.StartSessionOutput{
|
||||
SessionId: &id,
|
||||
StreamUrl: &url,
|
||||
TokenValue: &token,
|
||||
}
|
||||
return &output
|
||||
}
|
||||
|
||||
func MockStartSessionInput(instance string) ssm.StartSessionInput {
|
||||
params := map[string][]*string{
|
||||
"portNumber": []*string{aws.String("22")},
|
||||
"localPortNumber": []*string{aws.String("8001")},
|
||||
}
|
||||
|
||||
input := ssm.StartSessionInput{
|
||||
DocumentName: aws.String("AWS-StartPortForwardingSession"),
|
||||
Parameters: params,
|
||||
Target: aws.String(instance),
|
||||
}
|
||||
|
||||
return input
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/hashicorp/packer/common/net"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type StepCreateSSMTunnel struct {
|
||||
AWSSession *session.Session
|
||||
Region string
|
||||
LocalPortNumber int
|
||||
RemotePortNumber int
|
||||
SSMAgentEnabled bool
|
||||
instanceId string
|
||||
driver *SSMDriver
|
||||
}
|
||||
|
||||
// Run executes the Packer build step that creates a session tunnel.
|
||||
func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if !s.SSMAgentEnabled {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Configure local port number
|
||||
if err := s.ConfigureLocalHostPort(ctx); err != nil {
|
||||
err := fmt.Errorf("error finding an available port to initiate a session tunnel: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Get instance information
|
||||
instance, ok := state.Get("instance").(*ec2.Instance)
|
||||
if !ok {
|
||||
err := fmt.Errorf("error encountered in obtaining target instance id for session tunnel")
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
s.instanceId = aws.StringValue(instance.InstanceId)
|
||||
|
||||
if s.driver == nil {
|
||||
ssmconn := ssm.New(s.AWSSession)
|
||||
cfg := SSMDriverConfig{
|
||||
SvcClient: ssmconn,
|
||||
Region: s.Region,
|
||||
SvcEndpoint: ssmconn.Endpoint,
|
||||
}
|
||||
driver := SSMDriver{SSMDriverConfig: cfg}
|
||||
s.driver = &driver
|
||||
}
|
||||
|
||||
input := s.BuildTunnelInputForInstance(s.instanceId)
|
||||
_, err := s.driver.StartSession(ctx, input)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error encountered in establishing a tunnel %s", err)
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Message(fmt.Sprintf("PortForwarding session %q has been started", s.instanceId))
|
||||
state.Put("sessionPort", s.LocalPortNumber)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup terminates an active session on AWS, which in turn terminates the associated tunnel process running on the local machine.
|
||||
func (s *StepCreateSSMTunnel) Cleanup(state multistep.StateBag) {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
if !s.SSMAgentEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.driver.StopSession(); err != nil {
|
||||
ui.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigureLocalHostPort finds an available port on the localhost that can be used for the remote tunnel.
|
||||
// Defaults to using s.LocalPortNumber if it is set.
|
||||
func (s *StepCreateSSMTunnel) ConfigureLocalHostPort(ctx context.Context) error {
|
||||
minPortNumber, maxPortNumber := 8000, 9000
|
||||
|
||||
if s.LocalPortNumber != 0 {
|
||||
minPortNumber = s.LocalPortNumber
|
||||
maxPortNumber = minPortNumber
|
||||
}
|
||||
|
||||
// Find an available TCP port for our HTTP server
|
||||
l, err := net.ListenRangeConfig{
|
||||
Min: minPortNumber,
|
||||
Max: maxPortNumber,
|
||||
Addr: "0.0.0.0",
|
||||
Network: "tcp",
|
||||
}.Listen(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.LocalPortNumber = l.Port
|
||||
// Stop listening on selected port so that the AWS session-manager-plugin can use it.
|
||||
// The port is closed right before we start the session to avoid two Packer builds from getting the same port - fingers-crossed
|
||||
l.Close()
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (s *StepCreateSSMTunnel) BuildTunnelInputForInstance(instance string) ssm.StartSessionInput {
|
||||
dst, src := strconv.Itoa(s.RemotePortNumber), strconv.Itoa(s.LocalPortNumber)
|
||||
params := map[string][]*string{
|
||||
"portNumber": []*string{aws.String(dst)},
|
||||
"localPortNumber": []*string{aws.String(src)},
|
||||
}
|
||||
|
||||
input := ssm.StartSessionInput{
|
||||
DocumentName: aws.String("AWS-StartPortForwardingSession"),
|
||||
Parameters: params,
|
||||
Target: aws.String(instance),
|
||||
}
|
||||
|
||||
return input
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func TestStepCreateSSMTunnel_Run(t *testing.T) {
|
||||
mockSvc := MockSSMSvc{}
|
||||
config := SSMDriverConfig{
|
||||
SvcClient: &mockSvc,
|
||||
SvcEndpoint: "example.com",
|
||||
}
|
||||
|
||||
mockDriver := NewSSMDriver(config)
|
||||
mockDriver.pluginCmdFunc = MockPluginCmdFunc
|
||||
|
||||
state := testState()
|
||||
state.Put("ui", &packer.NoopUi{})
|
||||
state.Put("instance", &ec2.Instance{InstanceId: aws.String("i-something")})
|
||||
|
||||
step := StepCreateSSMTunnel{
|
||||
driver: mockDriver,
|
||||
}
|
||||
|
||||
step.Run(context.Background(), state)
|
||||
|
||||
err := state.Get("error")
|
||||
if err != nil {
|
||||
err = err.(error)
|
||||
t.Fatalf("the call to Run failed with an error when it should've executed: %v", err)
|
||||
}
|
||||
|
||||
if mockSvc.StartSessionCalled {
|
||||
t.Errorf("StartSession should not be called when SSMAgentEnabled is false")
|
||||
}
|
||||
|
||||
// Run when SSMAgentEnabled is true
|
||||
step.SSMAgentEnabled = true
|
||||
step.Run(context.Background(), state)
|
||||
|
||||
err = state.Get("error")
|
||||
if err != nil {
|
||||
err = err.(error)
|
||||
t.Fatalf("the call to Run failed with an error when it should've executed: %v", err)
|
||||
}
|
||||
|
||||
if !mockSvc.StartSessionCalled {
|
||||
t.Errorf("calling run with the correct inputs should call StartSession")
|
||||
}
|
||||
|
||||
step.Cleanup(state)
|
||||
if !mockSvc.TerminateSessionCalled {
|
||||
t.Errorf("calling cleanup on a successful run should call TerminateSession")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateSSMTunnel_Cleanup(t *testing.T) {
|
||||
mockSvc := MockSSMSvc{}
|
||||
config := SSMDriverConfig{
|
||||
SvcClient: &mockSvc,
|
||||
SvcEndpoint: "example.com",
|
||||
}
|
||||
|
||||
mockDriver := NewSSMDriver(config)
|
||||
mockDriver.pluginCmdFunc = MockPluginCmdFunc
|
||||
|
||||
step := StepCreateSSMTunnel{
|
||||
SSMAgentEnabled: true,
|
||||
driver: mockDriver,
|
||||
}
|
||||
|
||||
state := testState()
|
||||
state.Put("ui", &packer.NoopUi{})
|
||||
state.Put("instance", &ec2.Instance{InstanceId: aws.String("i-something")})
|
||||
|
||||
step.Cleanup(state)
|
||||
|
||||
if mockSvc.TerminateSessionCalled {
|
||||
t.Fatalf("calling cleanup on a non started session should not call TerminateSession")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestStepCreateSSMTunnel_BuildTunnelInputForInstance(t *testing.T) {
|
||||
step := StepCreateSSMTunnel{
|
||||
Region: "region",
|
||||
LocalPortNumber: 8001,
|
||||
RemotePortNumber: 22,
|
||||
SSMAgentEnabled: true,
|
||||
}
|
||||
|
||||
input := step.BuildTunnelInputForInstance("i-something")
|
||||
|
||||
target := aws.StringValue(input.Target)
|
||||
if target != "i-something" {
|
||||
t.Errorf("input should contain instance id as target but it got %q", target)
|
||||
}
|
||||
|
||||
params := map[string][]*string{
|
||||
"portNumber": []*string{aws.String("22")},
|
||||
"localPortNumber": []*string{aws.String("8001")},
|
||||
}
|
||||
if !reflect.DeepEqual(input.Parameters, params) {
|
||||
t.Errorf("input should contain the expected port parameters but it got %v", input.Parameters)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestStepCreateSSMTunnel_ConfigureLocalHostPort(t *testing.T) {
|
||||
tt := []struct {
|
||||
Name string
|
||||
Step StepCreateSSMTunnel
|
||||
PortCheck func(int) bool
|
||||
}{
|
||||
{"WithLocalPortNumber", StepCreateSSMTunnel{LocalPortNumber: 9001}, func(port int) bool { return port == 9001 }},
|
||||
{"WithNoLocalPortNumber", StepCreateSSMTunnel{}, func(port int) bool { return port >= 8000 && port <= 9000 }},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
step := tc.Step
|
||||
if err := step.ConfigureLocalHostPort(context.TODO()); err != nil {
|
||||
t.Errorf("failed to configure a port on localhost")
|
||||
}
|
||||
|
||||
if !tc.PortCheck(step.LocalPortNumber) {
|
||||
t.Errorf("failed to configure a port on localhost")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult
|
||||
|
||||
// Retry creating tags for about 2.5 minutes
|
||||
err = retry.Config{Tries: 11, ShouldRetry: func(error) bool {
|
||||
if IsAWSErr(err, "InvalidAMIID.NotFound", "") || IsAWSErr(err, "InvalidSnapshot.NotFound", "") {
|
||||
if isAWSErr(err, "InvalidAMIID.NotFound", "") || isAWSErr(err, "InvalidSnapshot.NotFound", "") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -39,7 +39,7 @@ func (s *StepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul
|
||||
err := retry.Config{
|
||||
Tries: 11,
|
||||
ShouldRetry: func(err error) bool {
|
||||
if IsAWSErr(err, "AuthFailure", "") {
|
||||
if isAWSErr(err, "AuthFailure", "") {
|
||||
log.Printf("Waiting for Vault-generated AWS credentials" +
|
||||
" to pass authentication... trying again.")
|
||||
return true
|
||||
@@ -131,7 +131,7 @@ func (s *StepPreValidate) checkVpc(conn ec2iface.EC2API) error {
|
||||
}
|
||||
|
||||
res, err := conn.DescribeVpcs(&ec2.DescribeVpcsInput{VpcIds: []*string{aws.String(s.VpcId)}})
|
||||
if IsAWSErr(err, "InvalidVpcID.NotFound", "") || err != nil {
|
||||
if isAWSErr(err, "InvalidVpcID.NotFound", "") || err != nil {
|
||||
return fmt.Errorf("Error retrieving VPC information for vpc_id %s: %s", s.VpcId, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
|
||||
err = retry.Config{
|
||||
Tries: 11,
|
||||
ShouldRetry: func(err error) bool {
|
||||
if IsAWSErr(err, "InvalidParameterValue", "iamInstanceProfile") {
|
||||
if isAWSErr(err, "InvalidParameterValue", "iamInstanceProfile") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -209,7 +209,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
|
||||
return err
|
||||
})
|
||||
|
||||
if IsAWSErr(err, "VPCIdNotSpecified", "No default VPC for this user") && subnetId == "" {
|
||||
if isAWSErr(err, "VPCIdNotSpecified", "No default VPC for this user") && subnetId == "" {
|
||||
err := fmt.Errorf("Error launching source instance: a valid Subnet Id was not specified")
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
@@ -247,7 +247,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
|
||||
|
||||
var r *ec2.DescribeInstancesOutput
|
||||
err = retry.Config{Tries: 11, ShouldRetry: func(err error) bool {
|
||||
if IsAWSErr(err, "InvalidInstanceID.NotFound", "") {
|
||||
if isAWSErr(err, "InvalidInstanceID.NotFound", "") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -292,7 +292,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
|
||||
ec2Tags.Report(ui)
|
||||
// Retry creating tags for about 2.5 minutes
|
||||
err = retry.Config{Tries: 11, ShouldRetry: func(error) bool {
|
||||
if IsAWSErr(err, "InvalidInstanceID.NotFound", "") {
|
||||
if isAWSErr(err, "InvalidInstanceID.NotFound", "") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -324,11 +324,6 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
|
||||
describeOutput, err = ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{
|
||||
InstanceIds: []*string{aws.String(instanceId)},
|
||||
})
|
||||
if len(describeOutput.Reservations) > 0 && len(describeOutput.Reservations[0].Instances) > 0 {
|
||||
if len(s.LaunchMappings.BuildEC2BlockDeviceMappings()) > 0 && len(describeOutput.Reservations[0].Instances[0].BlockDeviceMappings) == 0 {
|
||||
return fmt.Errorf("Instance has no block devices")
|
||||
}
|
||||
}
|
||||
return err
|
||||
})
|
||||
if err != nil || len(describeOutput.Reservations) == 0 || len(describeOutput.Reservations[0].Instances) == 0 {
|
||||
@@ -377,7 +372,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
|
||||
|
||||
// Retry creating tags for about 2.5 minutes
|
||||
err = retry.Config{Tries: 11, ShouldRetry: func(error) bool {
|
||||
if IsAWSErr(err, "InvalidInstanceID.NotFound", "") {
|
||||
if isAWSErr(err, "InvalidInstanceID.NotFound", "") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -21,7 +21,6 @@ type StepSecurityGroup struct {
|
||||
SecurityGroupFilter SecurityGroupFilterOptions
|
||||
SecurityGroupIds []string
|
||||
TemporarySGSourceCidrs []string
|
||||
SkipSSHRuleCreation bool
|
||||
|
||||
createdGroupId string
|
||||
}
|
||||
@@ -77,6 +76,13 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
port := s.CommConfig.Port()
|
||||
if port == 0 {
|
||||
if s.CommConfig.Type != "none" {
|
||||
panic("port must be set to a non-zero value.")
|
||||
}
|
||||
}
|
||||
|
||||
// Create the group
|
||||
groupName := fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID())
|
||||
ui.Say(fmt.Sprintf("Creating temporary security group for this instance: %s", groupName))
|
||||
@@ -104,15 +110,15 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m
|
||||
GroupIds: []*string{aws.String(s.createdGroupId)},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
log.Printf("[DEBUG] Found security group %s", s.createdGroupId)
|
||||
} else {
|
||||
err := fmt.Errorf("Timed out waiting for security group %s: %s", s.createdGroupId, err)
|
||||
log.Printf("[DEBUG] %s", err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Found security group %s", s.createdGroupId)
|
||||
|
||||
// map the list of temporary security group CIDRs bundled with config to
|
||||
// types expected by EC2.
|
||||
groupIpRanges := []*ec2.IpRange{}
|
||||
@@ -123,15 +129,7 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m
|
||||
groupIpRanges = append(groupIpRanges, &ipRange)
|
||||
}
|
||||
|
||||
// Set some state data for use in future steps
|
||||
state.Put("securityGroupIds", []string{s.createdGroupId})
|
||||
|
||||
if s.SkipSSHRuleCreation {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
port := s.CommConfig.Port()
|
||||
// Authorize access for the provided port within the security group
|
||||
// Authorize the SSH access for the security group
|
||||
groupRules := &ec2.AuthorizeSecurityGroupIngressInput{
|
||||
GroupId: groupResp.GroupId,
|
||||
IpPermissions: []*ec2.IpPermission{
|
||||
@@ -156,6 +154,9 @@ func (s *StepSecurityGroup) Run(ctx context.Context, state multistep.StateBag) m
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Set some state data for use in future steps
|
||||
state.Put("securityGroupIds", []string{s.createdGroupId})
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta
|
||||
|
||||
// Work around this by retrying a few times, up to about 5 minutes.
|
||||
err := retry.Config{Tries: 6, ShouldRetry: func(error) bool {
|
||||
if IsAWSErr(err, "InvalidInstanceID.NotFound", "") {
|
||||
if isAWSErr(err, "InvalidInstanceID.NotFound", "") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/hashicorp/packer/builder"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/hcl2template"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
@@ -55,12 +54,7 @@ type Config struct {
|
||||
// duplicated in `tags`. This is a [template
|
||||
// engine](/docs/templates/engine), see [Build template
|
||||
// data](#build-template-data) for more information.
|
||||
VolumeRunTags map[string]string `mapstructure:"run_volume_tags"`
|
||||
// Same as [`run_volume_tags`](#run_volume_tags) but defined as a singular
|
||||
// block containing a `name` and a `value` field. In HCL2 mode the
|
||||
// [`dynamic_block`](https://packer.io/docs/configuration/from-1.5/expressions.html#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
VolumeRunTag hcl2template.NameValues `mapstructure:"run_volume_tag" required:"false"`
|
||||
VolumeRunTags awscommon.TagMap `mapstructure:"run_volume_tags"`
|
||||
// Relevant only to Windows guests: If you set this flag, we'll add clauses
|
||||
// to the launch_block_device_mappings that make sure ephemeral drives
|
||||
// don't show up in the EC2 console. If you launched from the EC2 console,
|
||||
@@ -110,8 +104,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
var errs *packer.MultiError
|
||||
var warns []string
|
||||
|
||||
errs = packer.MultiErrorAppend(errs, b.config.VolumeRunTag.CopyOn(&b.config.VolumeRunTags)...)
|
||||
|
||||
errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(&b.config.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs,
|
||||
b.config.AMIConfig.Prepare(&b.config.AccessConfig, &b.config.ctx)...)
|
||||
@@ -247,7 +239,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
SecurityGroupIds: b.config.SecurityGroupIds,
|
||||
CommConfig: &b.config.RunConfig.Comm,
|
||||
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
|
||||
SkipSSHRuleCreation: b.config.SSMAgentEnabled(),
|
||||
},
|
||||
&awscommon.StepIamInstanceProfile{
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
@@ -264,13 +255,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
Timeout: b.config.WindowsPasswordTimeout,
|
||||
BuildName: b.config.PackerBuildName,
|
||||
},
|
||||
&awscommon.StepCreateSSMTunnel{
|
||||
AWSSession: session,
|
||||
Region: *ec2conn.Config.Region,
|
||||
LocalPortNumber: b.config.SessionManagerPort,
|
||||
RemotePortNumber: b.config.Comm.Port(),
|
||||
SSMAgentEnabled: b.config.SSMAgentEnabled(),
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.RunConfig.Comm,
|
||||
Host: awscommon.SSHHost(
|
||||
@@ -278,10 +262,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
b.config.SSHInterface,
|
||||
b.config.Comm.Host(),
|
||||
),
|
||||
SSHPort: awscommon.Port(
|
||||
b.config.SSHInterface,
|
||||
b.config.Comm.Port(),
|
||||
),
|
||||
SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(),
|
||||
},
|
||||
&common.StepProvision{},
|
||||
|
||||
@@ -11,132 +11,124 @@ 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" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key" hcl:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2" hcl:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages" hcl:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify" hcl:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries" hcl:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code" hcl:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile" hcl:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region" hcl:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key" hcl:"secret_key"`
|
||||
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation" hcl:"skip_region_validation"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name" hcl:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description" hcl:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type" hcl:"ami_virtualization_type"`
|
||||
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users" hcl:"ami_users"`
|
||||
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups" hcl:"ami_groups"`
|
||||
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes" hcl:"ami_product_codes"`
|
||||
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions" hcl:"ami_regions"`
|
||||
AMITags map[string]string `mapstructure:"tags" required:"false" cty:"tags" hcl:"tags"`
|
||||
AMITag []hcl2template.FlatKeyValue `mapstructure:"tag" required:"false" cty:"tag" hcl:"tag"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support" hcl:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support" hcl:"sriov_support"`
|
||||
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister" hcl:"force_deregister"`
|
||||
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot" hcl:"force_delete_snapshot"`
|
||||
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot" hcl:"encrypt_boot"`
|
||||
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"`
|
||||
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids" hcl:"region_kms_key_ids"`
|
||||
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region" hcl:"skip_save_build_region"`
|
||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags" hcl:"snapshot_tags"`
|
||||
SnapshotTag []hcl2template.FlatKeyValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag" hcl:"snapshot_tag"`
|
||||
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users" hcl:"snapshot_users"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups" hcl:"snapshot_groups"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address" hcl:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone" hcl:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes" hcl:"block_duration_minutes"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"`
|
||||
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized" hcl:"ebs_optimized"`
|
||||
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited" hcl:"enable_t2_unlimited"`
|
||||
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile" hcl:"iam_instance_profile"`
|
||||
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation" hcl:"skip_profile_validation"`
|
||||
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document" hcl:"temporary_iam_instance_profile_policy_document"`
|
||||
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior" hcl:"shutdown_behavior"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type" hcl:"instance_type"`
|
||||
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter" hcl:"security_group_filter"`
|
||||
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags" hcl:"run_tags"`
|
||||
RunTag []hcl2template.FlatKeyValue `mapstructure:"run_tag" required:"false" cty:"run_tag" hcl:"run_tag"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"`
|
||||
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids" hcl:"security_group_ids"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami" hcl:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter" hcl:"source_ami_filter"`
|
||||
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types" hcl:"spot_instance_types"`
|
||||
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price" hcl:"spot_price"`
|
||||
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" undocumented:"true" cty:"spot_price_auto_product" hcl:"spot_price_auto_product"`
|
||||
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags" hcl:"spot_tags"`
|
||||
SpotTag []hcl2template.FlatKeyValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag" hcl:"spot_tag"`
|
||||
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter" hcl:"subnet_filter"`
|
||||
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
|
||||
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
|
||||
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs" hcl:"temporary_security_group_source_cidrs"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file" hcl:"user_data_file"`
|
||||
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter" hcl:"vpc_filter"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"`
|
||||
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout" hcl:"windows_password_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
|
||||
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
|
||||
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"`
|
||||
SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"`
|
||||
SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"`
|
||||
WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
||||
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface" hcl:"ssh_interface"`
|
||||
SessionManagerPort *int `mapstructure:"session_manager_port" cty:"session_manager_port" hcl:"session_manager_port"`
|
||||
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings" hcl:"ami_block_device_mappings"`
|
||||
LaunchMappings []common.FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings" hcl:"launch_block_device_mappings"`
|
||||
VolumeRunTags map[string]string `mapstructure:"run_volume_tags" cty:"run_volume_tags" hcl:"run_volume_tags"`
|
||||
VolumeRunTag []hcl2template.FlatNameValue `mapstructure:"run_volume_tag" required:"false" cty:"run_volume_tag" hcl:"run_volume_tag"`
|
||||
NoEphemeral *bool `mapstructure:"no_ephemeral" required:"false" cty:"no_ephemeral" hcl:"no_ephemeral"`
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
|
||||
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type"`
|
||||
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users"`
|
||||
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups"`
|
||||
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes"`
|
||||
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions"`
|
||||
AMITags map[string]string `mapstructure:"tags" required:"false" cty:"tags"`
|
||||
AMITag []hcl2template.FlatNameValue `mapstructure:"tag" required:"false" cty:"tag"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
|
||||
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
|
||||
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
|
||||
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
|
||||
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
|
||||
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
|
||||
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
|
||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
|
||||
SnapshotTag []hcl2template.FlatNameValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag"`
|
||||
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
|
||||
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
|
||||
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
|
||||
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
|
||||
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
|
||||
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
|
||||
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
|
||||
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter"`
|
||||
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags"`
|
||||
RunTag []hcl2template.FlatNameValue `mapstructure:"run_tag" required:"false" cty:"run_tag"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
|
||||
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
|
||||
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
|
||||
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
|
||||
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
|
||||
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
|
||||
SpotTag []hcl2template.FlatNameValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag"`
|
||||
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
|
||||
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
|
||||
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
|
||||
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
|
||||
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
|
||||
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
||||
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
|
||||
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"`
|
||||
LaunchMappings []common.FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings"`
|
||||
VolumeRunTags common.TagMap `mapstructure:"run_volume_tags" cty:"run_volume_tags"`
|
||||
NoEphemeral *bool `mapstructure:"no_ephemeral" required:"false" cty:"no_ephemeral"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
@@ -179,7 +171,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},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
|
||||
@@ -189,7 +181,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
|
||||
@@ -205,7 +197,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "run_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_tag": &hcldec.BlockListSpec{TypeName: "run_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
|
||||
@@ -214,7 +206,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "spot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
||||
@@ -231,14 +223,10 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
|
||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
||||
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
||||
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
||||
"ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false},
|
||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
||||
@@ -249,7 +237,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
||||
@@ -264,18 +251,15 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
||||
"winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
|
||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
|
||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||
"ssh_interface": &hcldec.AttrSpec{Name: "ssh_interface", Type: cty.String, Required: false},
|
||||
"session_manager_port": &hcldec.AttrSpec{Name: "session_manager_port", Type: cty.Number, 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.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())},
|
||||
"no_ephemeral": &hcldec.AttrSpec{Name: "no_ephemeral", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
|
||||
@@ -4,13 +4,11 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common/random"
|
||||
"github.com/hashicorp/packer/common/retry"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
@@ -50,26 +48,7 @@ func (s *stepCreateAMI) Run(ctx context.Context, state multistep.StateBag) multi
|
||||
BlockDeviceMappings: config.AMIMappings.BuildEC2BlockDeviceMappings(),
|
||||
}
|
||||
|
||||
var createResp *ec2.CreateImageOutput
|
||||
var err error
|
||||
|
||||
// Create a timeout for the CreateImage call.
|
||||
timeoutCtx, cancel := context.WithTimeout(ctx, time.Minute*15)
|
||||
defer cancel()
|
||||
|
||||
err = retry.Config{
|
||||
Tries: 0,
|
||||
ShouldRetry: func(err error) bool {
|
||||
if awscommon.IsAWSErr(err, "InvalidParameterValue", "Instance is not in state") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear,
|
||||
}.Run(timeoutCtx, func(ctx context.Context) error {
|
||||
createResp, err = ec2conn.CreateImage(createOpts)
|
||||
return err
|
||||
})
|
||||
createResp, err := ec2conn.CreateImage(createOpts)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error creating AMI: %s", err)
|
||||
state.Put("error", err)
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/hashicorp/packer/builder"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/hcl2template"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
@@ -61,12 +60,7 @@ type Config struct {
|
||||
// duplicated in `tags`. This is a [template
|
||||
// engine](/docs/templates/engine), see [Build template
|
||||
// data](#build-template-data) for more information.
|
||||
VolumeRunTags map[string]string `mapstructure:"run_volume_tags"`
|
||||
// Same as [`run_volume_tags`](#run_volume_tags) but defined as a singular
|
||||
// block containing a `name` and a `value` field. In HCL2 mode the
|
||||
// [`dynamic_block`](https://packer.io/docs/configuration/from-1.5/expressions.html#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
VolumeRunTag hcl2template.NameValues `mapstructure:"run_volume_tag" required:"false"`
|
||||
VolumeRunTags awscommon.TagMap `mapstructure:"run_volume_tags"`
|
||||
// what architecture to use when registering the
|
||||
// final AMI; valid options are "x86_64" or "arm64". Defaults to "x86_64".
|
||||
Architecture string `mapstructure:"ami_architecture" required:"false"`
|
||||
@@ -108,8 +102,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
// Accumulate any errors
|
||||
var errs *packer.MultiError
|
||||
var warns []string
|
||||
errs = packer.MultiErrorAppend(errs, b.config.VolumeRunTag.CopyOn(&b.config.VolumeRunTags)...)
|
||||
|
||||
errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(&b.config.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs,
|
||||
@@ -270,7 +262,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
SecurityGroupIds: b.config.SecurityGroupIds,
|
||||
CommConfig: &b.config.RunConfig.Comm,
|
||||
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
|
||||
SkipSSHRuleCreation: b.config.SSMAgentEnabled(),
|
||||
},
|
||||
&awscommon.StepIamInstanceProfile{
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
@@ -287,13 +278,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
Timeout: b.config.WindowsPasswordTimeout,
|
||||
BuildName: b.config.PackerBuildName,
|
||||
},
|
||||
&awscommon.StepCreateSSMTunnel{
|
||||
AWSSession: session,
|
||||
Region: *ec2conn.Config.Region,
|
||||
LocalPortNumber: b.config.SessionManagerPort,
|
||||
RemotePortNumber: b.config.Comm.Port(),
|
||||
SSMAgentEnabled: b.config.SSMAgentEnabled(),
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.RunConfig.Comm,
|
||||
Host: awscommon.SSHHost(
|
||||
@@ -301,10 +285,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
b.config.SSHInterface,
|
||||
b.config.Comm.Host(),
|
||||
),
|
||||
SSHPort: awscommon.Port(
|
||||
b.config.SSHInterface,
|
||||
b.config.Comm.Port(),
|
||||
),
|
||||
SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(),
|
||||
},
|
||||
&common.StepProvision{},
|
||||
|
||||
@@ -11,17 +11,17 @@ import (
|
||||
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatBlockDevice struct {
|
||||
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" hcl:"delete_on_termination"`
|
||||
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name" hcl:"device_name"`
|
||||
Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted" hcl:"encrypted"`
|
||||
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops" hcl:"iops"`
|
||||
NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device" hcl:"no_device"`
|
||||
SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id" hcl:"snapshot_id"`
|
||||
VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name" hcl:"virtual_name"`
|
||||
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type" hcl:"volume_type"`
|
||||
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size" hcl:"volume_size"`
|
||||
KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"`
|
||||
OmitFromArtifact *bool `mapstructure:"omit_from_artifact" cty:"omit_from_artifact" hcl:"omit_from_artifact"`
|
||||
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination"`
|
||||
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name"`
|
||||
Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted"`
|
||||
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops"`
|
||||
NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device"`
|
||||
SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id"`
|
||||
VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name"`
|
||||
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type"`
|
||||
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size"`
|
||||
KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
|
||||
OmitFromArtifact *bool `mapstructure:"omit_from_artifact" cty:"omit_from_artifact"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatBlockDevice.
|
||||
@@ -54,133 +54,125 @@ func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
|
||||
// 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" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key" hcl:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2" hcl:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages" hcl:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify" hcl:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries" hcl:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code" hcl:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile" hcl:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region" hcl:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key" hcl:"secret_key"`
|
||||
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation" hcl:"skip_region_validation"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address" hcl:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone" hcl:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes" hcl:"block_duration_minutes"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"`
|
||||
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized" hcl:"ebs_optimized"`
|
||||
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited" hcl:"enable_t2_unlimited"`
|
||||
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile" hcl:"iam_instance_profile"`
|
||||
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation" hcl:"skip_profile_validation"`
|
||||
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document" hcl:"temporary_iam_instance_profile_policy_document"`
|
||||
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior" hcl:"shutdown_behavior"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type" hcl:"instance_type"`
|
||||
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter" hcl:"security_group_filter"`
|
||||
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags" hcl:"run_tags"`
|
||||
RunTag []hcl2template.FlatKeyValue `mapstructure:"run_tag" required:"false" cty:"run_tag" hcl:"run_tag"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"`
|
||||
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids" hcl:"security_group_ids"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami" hcl:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter" hcl:"source_ami_filter"`
|
||||
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types" hcl:"spot_instance_types"`
|
||||
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price" hcl:"spot_price"`
|
||||
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" undocumented:"true" cty:"spot_price_auto_product" hcl:"spot_price_auto_product"`
|
||||
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags" hcl:"spot_tags"`
|
||||
SpotTag []hcl2template.FlatKeyValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag" hcl:"spot_tag"`
|
||||
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter" hcl:"subnet_filter"`
|
||||
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
|
||||
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
|
||||
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs" hcl:"temporary_security_group_source_cidrs"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file" hcl:"user_data_file"`
|
||||
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter" hcl:"vpc_filter"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"`
|
||||
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout" hcl:"windows_password_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
|
||||
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
|
||||
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"`
|
||||
SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"`
|
||||
SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"`
|
||||
WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
||||
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface" hcl:"ssh_interface"`
|
||||
SessionManagerPort *int `mapstructure:"session_manager_port" cty:"session_manager_port" hcl:"session_manager_port"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name" hcl:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description" hcl:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type" hcl:"ami_virtualization_type"`
|
||||
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users" hcl:"ami_users"`
|
||||
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups" hcl:"ami_groups"`
|
||||
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes" hcl:"ami_product_codes"`
|
||||
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions" hcl:"ami_regions"`
|
||||
AMITags map[string]string `mapstructure:"tags" required:"false" cty:"tags" hcl:"tags"`
|
||||
AMITag []hcl2template.FlatKeyValue `mapstructure:"tag" required:"false" cty:"tag" hcl:"tag"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support" hcl:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support" hcl:"sriov_support"`
|
||||
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister" hcl:"force_deregister"`
|
||||
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot" hcl:"force_delete_snapshot"`
|
||||
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot" hcl:"encrypt_boot"`
|
||||
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"`
|
||||
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids" hcl:"region_kms_key_ids"`
|
||||
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region" hcl:"skip_save_build_region"`
|
||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags" hcl:"snapshot_tags"`
|
||||
SnapshotTag []hcl2template.FlatKeyValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag" hcl:"snapshot_tag"`
|
||||
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users" hcl:"snapshot_users"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups" hcl:"snapshot_groups"`
|
||||
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings" hcl:"ami_block_device_mappings"`
|
||||
LaunchMappings []FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings" hcl:"launch_block_device_mappings"`
|
||||
RootDevice *FlatRootBlockDevice `mapstructure:"ami_root_device" required:"true" cty:"ami_root_device" hcl:"ami_root_device"`
|
||||
VolumeRunTags map[string]string `mapstructure:"run_volume_tags" cty:"run_volume_tags" hcl:"run_volume_tags"`
|
||||
VolumeRunTag []hcl2template.FlatNameValue `mapstructure:"run_volume_tag" required:"false" cty:"run_volume_tag" hcl:"run_volume_tag"`
|
||||
Architecture *string `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture" hcl:"ami_architecture"`
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
|
||||
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
|
||||
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
|
||||
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
|
||||
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
|
||||
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
|
||||
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
|
||||
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
|
||||
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter"`
|
||||
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags"`
|
||||
RunTag []hcl2template.FlatNameValue `mapstructure:"run_tag" required:"false" cty:"run_tag"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
|
||||
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
|
||||
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
|
||||
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
|
||||
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
|
||||
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
|
||||
SpotTag []hcl2template.FlatNameValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag"`
|
||||
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
|
||||
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
|
||||
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
|
||||
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
|
||||
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
|
||||
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
||||
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type"`
|
||||
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users"`
|
||||
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups"`
|
||||
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes"`
|
||||
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions"`
|
||||
AMITags map[string]string `mapstructure:"tags" required:"false" cty:"tags"`
|
||||
AMITag []hcl2template.FlatNameValue `mapstructure:"tag" required:"false" cty:"tag"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
|
||||
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
|
||||
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
|
||||
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
|
||||
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
|
||||
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
|
||||
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
|
||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
|
||||
SnapshotTag []hcl2template.FlatNameValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag"`
|
||||
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
|
||||
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"`
|
||||
LaunchMappings []FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings"`
|
||||
RootDevice *FlatRootBlockDevice `mapstructure:"ami_root_device" required:"true" cty:"ami_root_device"`
|
||||
VolumeRunTags common.TagMap `mapstructure:"run_volume_tags" cty:"run_volume_tags"`
|
||||
Architecture *string `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
@@ -228,7 +220,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "run_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_tag": &hcldec.BlockListSpec{TypeName: "run_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
|
||||
@@ -237,7 +229,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "spot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
||||
@@ -254,14 +246,10 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
|
||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
||||
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
||||
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
||||
"ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false},
|
||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
||||
@@ -272,7 +260,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
||||
@@ -287,14 +274,12 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
||||
"winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
|
||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
|
||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||
"ssh_interface": &hcldec.AttrSpec{Name: "ssh_interface", Type: cty.String, Required: false},
|
||||
"session_manager_port": &hcldec.AttrSpec{Name: "session_manager_port", Type: cty.Number, Required: false},
|
||||
"ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
|
||||
"ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false},
|
||||
"ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false},
|
||||
@@ -303,7 +288,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},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
|
||||
@@ -313,14 +298,13 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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.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())},
|
||||
"ami_architecture": &hcldec.AttrSpec{Name: "ami_architecture", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
@@ -329,12 +313,12 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
// FlatRootBlockDevice is an auto-generated flat version of RootBlockDevice.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatRootBlockDevice struct {
|
||||
SourceDeviceName *string `mapstructure:"source_device_name" cty:"source_device_name" hcl:"source_device_name"`
|
||||
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name" hcl:"device_name"`
|
||||
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" hcl:"delete_on_termination"`
|
||||
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops" hcl:"iops"`
|
||||
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type" hcl:"volume_type"`
|
||||
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size" hcl:"volume_size"`
|
||||
SourceDeviceName *string `mapstructure:"source_device_name" cty:"source_device_name"`
|
||||
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name"`
|
||||
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination"`
|
||||
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops"`
|
||||
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type"`
|
||||
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatRootBlockDevice.
|
||||
|
||||
@@ -11,15 +11,15 @@ import (
|
||||
|
||||
type BlockDevice struct {
|
||||
awscommon.BlockDevice `mapstructure:",squash"`
|
||||
// Key/value pair tags to apply to the volume. These are retained after the builder
|
||||
// Tags to apply to the volume. These are retained after the builder
|
||||
// completes. This is a [template engine](/docs/templates/engine), see
|
||||
// [Build template data](#build-template-data) for more information.
|
||||
Tags map[string]string `mapstructure:"tags" required:"false"`
|
||||
// Same as [`tags`](#tags) but defined as a singular repeatable block
|
||||
// containing a `key` and a `value` field. In HCL2 mode the
|
||||
// containing a `name` and a `value` field. In HCL2 mode the
|
||||
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
Tag hcl2template.KeyValues `mapstructure:"tag" required:"false"`
|
||||
Tag hcl2template.NameValues `mapstructure:"tag" required:"false"`
|
||||
}
|
||||
|
||||
type BlockDevices []BlockDevice
|
||||
|
||||
@@ -53,10 +53,10 @@ type Config struct {
|
||||
// source instance. See the [BlockDevices](#block-devices-configuration)
|
||||
// documentation for fields.
|
||||
VolumeMappings BlockDevices `mapstructure:"ebs_volumes" required:"false"`
|
||||
// Key/value pair tags to apply to the volumes of the instance that is
|
||||
// *launched* to create EBS Volumes. These tags will *not* appear in the
|
||||
// tags of the resulting EBS volumes unless they're duplicated under `tags`
|
||||
// in the `ebs_volumes` setting. This is a [template
|
||||
// Tags to apply to the volumes of the instance that is *launched* to
|
||||
// create EBS Volumes. These tags will *not* appear in the tags of the
|
||||
// resulting EBS volumes unless they're duplicated under `tags` in the
|
||||
// `ebs_volumes` setting. This is a [template
|
||||
// engine](/docs/templates/engine), see [Build template
|
||||
// data](#build-template-data) for more information.
|
||||
//
|
||||
@@ -67,11 +67,11 @@ type Config struct {
|
||||
// reported as 'ready'.
|
||||
VolumeRunTags map[string]string `mapstructure:"run_volume_tags"`
|
||||
// Same as [`run_volume_tags`](#run_volume_tags) but defined as a singular
|
||||
// repeatable block containing a `key` and a `value` field. In HCL2 mode
|
||||
// repeatable block containing a `name` and a `value` field. In HCL2 mode
|
||||
// the
|
||||
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
VolumeRunTag hcl2template.KeyValues `mapstructure:"run_volume_tag"`
|
||||
VolumeRunTag hcl2template.NameValues `mapstructure:"run_volume_tag"`
|
||||
|
||||
launchBlockDevices BlockDevices
|
||||
|
||||
@@ -238,7 +238,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
SecurityGroupIds: b.config.SecurityGroupIds,
|
||||
CommConfig: &b.config.RunConfig.Comm,
|
||||
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
|
||||
SkipSSHRuleCreation: b.config.SSMAgentEnabled(),
|
||||
},
|
||||
&awscommon.StepIamInstanceProfile{
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
@@ -256,13 +255,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
Timeout: b.config.WindowsPasswordTimeout,
|
||||
BuildName: b.config.PackerBuildName,
|
||||
},
|
||||
&awscommon.StepCreateSSMTunnel{
|
||||
AWSSession: session,
|
||||
Region: *ec2conn.Config.Region,
|
||||
LocalPortNumber: b.config.SessionManagerPort,
|
||||
RemotePortNumber: b.config.Comm.Port(),
|
||||
SSMAgentEnabled: b.config.SSMAgentEnabled(),
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.RunConfig.Comm,
|
||||
Host: awscommon.SSHHost(
|
||||
@@ -270,10 +262,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
b.config.SSHInterface,
|
||||
b.config.Comm.Host(),
|
||||
),
|
||||
SSHPort: awscommon.Port(
|
||||
b.config.SSHInterface,
|
||||
b.config.Comm.Port(),
|
||||
),
|
||||
SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(),
|
||||
},
|
||||
&common.StepProvision{},
|
||||
|
||||
@@ -11,18 +11,18 @@ import (
|
||||
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatBlockDevice struct {
|
||||
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" hcl:"delete_on_termination"`
|
||||
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name" hcl:"device_name"`
|
||||
Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted" hcl:"encrypted"`
|
||||
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops" hcl:"iops"`
|
||||
NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device" hcl:"no_device"`
|
||||
SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id" hcl:"snapshot_id"`
|
||||
VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name" hcl:"virtual_name"`
|
||||
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type" hcl:"volume_type"`
|
||||
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size" hcl:"volume_size"`
|
||||
KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"`
|
||||
Tags map[string]string `mapstructure:"tags" required:"false" cty:"tags" hcl:"tags"`
|
||||
Tag []hcl2template.FlatKeyValue `mapstructure:"tag" required:"false" cty:"tag" hcl:"tag"`
|
||||
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination"`
|
||||
DeviceName *string `mapstructure:"device_name" required:"false" cty:"device_name"`
|
||||
Encrypted *bool `mapstructure:"encrypted" required:"false" cty:"encrypted"`
|
||||
IOPS *int64 `mapstructure:"iops" required:"false" cty:"iops"`
|
||||
NoDevice *bool `mapstructure:"no_device" required:"false" cty:"no_device"`
|
||||
SnapshotId *string `mapstructure:"snapshot_id" required:"false" cty:"snapshot_id"`
|
||||
VirtualName *string `mapstructure:"virtual_name" required:"false" cty:"virtual_name"`
|
||||
VolumeType *string `mapstructure:"volume_type" required:"false" cty:"volume_type"`
|
||||
VolumeSize *int64 `mapstructure:"volume_size" required:"false" cty:"volume_size"`
|
||||
KmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
|
||||
Tags map[string]string `mapstructure:"tags" required:"false" cty:"tags"`
|
||||
Tag []hcl2template.FlatNameValue `mapstructure:"tag" required:"false" cty:"tag"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatBlockDevice.
|
||||
@@ -48,7 +48,7 @@ func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -56,111 +56,104 @@ func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
|
||||
// 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" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key" hcl:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2" hcl:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages" hcl:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify" hcl:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries" hcl:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code" hcl:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile" hcl:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region" hcl:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key" hcl:"secret_key"`
|
||||
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation" hcl:"skip_region_validation"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address" hcl:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone" hcl:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes" hcl:"block_duration_minutes"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"`
|
||||
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized" hcl:"ebs_optimized"`
|
||||
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited" hcl:"enable_t2_unlimited"`
|
||||
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile" hcl:"iam_instance_profile"`
|
||||
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation" hcl:"skip_profile_validation"`
|
||||
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document" hcl:"temporary_iam_instance_profile_policy_document"`
|
||||
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior" hcl:"shutdown_behavior"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type" hcl:"instance_type"`
|
||||
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter" hcl:"security_group_filter"`
|
||||
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags" hcl:"run_tags"`
|
||||
RunTag []hcl2template.FlatKeyValue `mapstructure:"run_tag" required:"false" cty:"run_tag" hcl:"run_tag"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"`
|
||||
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids" hcl:"security_group_ids"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami" hcl:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter" hcl:"source_ami_filter"`
|
||||
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types" hcl:"spot_instance_types"`
|
||||
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price" hcl:"spot_price"`
|
||||
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" undocumented:"true" cty:"spot_price_auto_product" hcl:"spot_price_auto_product"`
|
||||
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags" hcl:"spot_tags"`
|
||||
SpotTag []hcl2template.FlatKeyValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag" hcl:"spot_tag"`
|
||||
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter" hcl:"subnet_filter"`
|
||||
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
|
||||
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
|
||||
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs" hcl:"temporary_security_group_source_cidrs"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file" hcl:"user_data_file"`
|
||||
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter" hcl:"vpc_filter"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"`
|
||||
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout" hcl:"windows_password_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
|
||||
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
|
||||
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"`
|
||||
SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"`
|
||||
SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"`
|
||||
WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
||||
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface" hcl:"ssh_interface"`
|
||||
SessionManagerPort *int `mapstructure:"session_manager_port" cty:"session_manager_port" hcl:"session_manager_port"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support" hcl:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support" hcl:"sriov_support"`
|
||||
VolumeMappings []FlatBlockDevice `mapstructure:"ebs_volumes" required:"false" cty:"ebs_volumes" hcl:"ebs_volumes"`
|
||||
VolumeRunTags map[string]string `mapstructure:"run_volume_tags" cty:"run_volume_tags" hcl:"run_volume_tags"`
|
||||
VolumeRunTag []hcl2template.FlatKeyValue `mapstructure:"run_volume_tag" cty:"run_volume_tag" hcl:"run_volume_tag"`
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
|
||||
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
|
||||
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
|
||||
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
|
||||
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
|
||||
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
|
||||
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
|
||||
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
|
||||
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter"`
|
||||
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags"`
|
||||
RunTag []hcl2template.FlatNameValue `mapstructure:"run_tag" required:"false" cty:"run_tag"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
|
||||
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
|
||||
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
|
||||
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
|
||||
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
|
||||
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
|
||||
SpotTag []hcl2template.FlatNameValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag"`
|
||||
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
|
||||
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
|
||||
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
|
||||
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
|
||||
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
|
||||
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
||||
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
|
||||
VolumeMappings []FlatBlockDevice `mapstructure:"ebs_volumes" required:"false" cty:"ebs_volumes"`
|
||||
VolumeRunTags map[string]string `mapstructure:"run_volume_tags" cty:"run_volume_tags"`
|
||||
VolumeRunTag []hcl2template.FlatNameValue `mapstructure:"run_volume_tag" cty:"run_volume_tag"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
@@ -208,7 +201,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "run_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_tag": &hcldec.BlockListSpec{TypeName: "run_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
|
||||
@@ -217,7 +210,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "spot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
||||
@@ -234,14 +227,10 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
|
||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
||||
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
||||
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
||||
"ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false},
|
||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
||||
@@ -252,7 +241,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
||||
@@ -267,19 +255,17 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
||||
"winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
|
||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
|
||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||
"ssh_interface": &hcldec.AttrSpec{Name: "ssh_interface", Type: cty.String, Required: false},
|
||||
"session_manager_port": &hcldec.AttrSpec{Name: "session_manager_port", Type: cty.Number, Required: false},
|
||||
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
|
||||
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
|
||||
"ebs_volumes": &hcldec.BlockListSpec{TypeName: "ebs_volumes", Nested: hcldec.ObjectSpec((*FlatBlockDevice)(nil).HCL2Spec())},
|
||||
"run_volume_tags": &hcldec.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.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"run_volume_tag": &hcldec.BlockListSpec{TypeName: "run_volume_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -324,7 +324,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
SecurityGroupFilter: b.config.SecurityGroupFilter,
|
||||
SecurityGroupIds: b.config.SecurityGroupIds,
|
||||
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
|
||||
SkipSSHRuleCreation: b.config.SSMAgentEnabled(),
|
||||
},
|
||||
&awscommon.StepIamInstanceProfile{
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
@@ -338,26 +337,13 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
Timeout: b.config.WindowsPasswordTimeout,
|
||||
BuildName: b.config.PackerBuildName,
|
||||
},
|
||||
&awscommon.StepCreateSSMTunnel{
|
||||
AWSSession: session,
|
||||
Region: *ec2conn.Config.Region,
|
||||
LocalPortNumber: b.config.SessionManagerPort,
|
||||
RemotePortNumber: b.config.Comm.Port(),
|
||||
SSMAgentEnabled: b.config.SSMAgentEnabled(),
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
// StepConnect is provided settings for WinRM and SSH, but
|
||||
// the communicator will ultimately determine which port to use.
|
||||
Config: &b.config.RunConfig.Comm,
|
||||
Host: awscommon.SSHHost(
|
||||
ec2conn,
|
||||
b.config.SSHInterface,
|
||||
b.config.Comm.Host(),
|
||||
),
|
||||
SSHPort: awscommon.Port(
|
||||
b.config.SSHInterface,
|
||||
b.config.Comm.Port(),
|
||||
),
|
||||
SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(),
|
||||
},
|
||||
&common.StepProvision{},
|
||||
|
||||
@@ -11,138 +11,131 @@ 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" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key" hcl:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2" hcl:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages" hcl:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify" hcl:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries" hcl:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code" hcl:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile" hcl:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region" hcl:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key" hcl:"secret_key"`
|
||||
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation" hcl:"skip_region_validation"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check" hcl:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine" hcl:"vault_aws_engine"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name" hcl:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description" hcl:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type" hcl:"ami_virtualization_type"`
|
||||
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users" hcl:"ami_users"`
|
||||
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups" hcl:"ami_groups"`
|
||||
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes" hcl:"ami_product_codes"`
|
||||
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions" hcl:"ami_regions"`
|
||||
AMITags map[string]string `mapstructure:"tags" required:"false" cty:"tags" hcl:"tags"`
|
||||
AMITag []hcl2template.FlatKeyValue `mapstructure:"tag" required:"false" cty:"tag" hcl:"tag"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support" hcl:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support" hcl:"sriov_support"`
|
||||
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister" hcl:"force_deregister"`
|
||||
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot" hcl:"force_delete_snapshot"`
|
||||
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot" hcl:"encrypt_boot"`
|
||||
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id" hcl:"kms_key_id"`
|
||||
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids" hcl:"region_kms_key_ids"`
|
||||
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region" hcl:"skip_save_build_region"`
|
||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags" hcl:"snapshot_tags"`
|
||||
SnapshotTag []hcl2template.FlatKeyValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag" hcl:"snapshot_tag"`
|
||||
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users" hcl:"snapshot_users"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups" hcl:"snapshot_groups"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address" hcl:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone" hcl:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes" hcl:"block_duration_minutes"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"`
|
||||
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized" hcl:"ebs_optimized"`
|
||||
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited" hcl:"enable_t2_unlimited"`
|
||||
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile" hcl:"iam_instance_profile"`
|
||||
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation" hcl:"skip_profile_validation"`
|
||||
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document" hcl:"temporary_iam_instance_profile_policy_document"`
|
||||
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior" hcl:"shutdown_behavior"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type" hcl:"instance_type"`
|
||||
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter" hcl:"security_group_filter"`
|
||||
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags" hcl:"run_tags"`
|
||||
RunTag []hcl2template.FlatKeyValue `mapstructure:"run_tag" required:"false" cty:"run_tag" hcl:"run_tag"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"`
|
||||
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids" hcl:"security_group_ids"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami" hcl:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter" hcl:"source_ami_filter"`
|
||||
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types" hcl:"spot_instance_types"`
|
||||
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price" hcl:"spot_price"`
|
||||
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" undocumented:"true" cty:"spot_price_auto_product" hcl:"spot_price_auto_product"`
|
||||
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags" hcl:"spot_tags"`
|
||||
SpotTag []hcl2template.FlatKeyValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag" hcl:"spot_tag"`
|
||||
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter" hcl:"subnet_filter"`
|
||||
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
|
||||
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
|
||||
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs" hcl:"temporary_security_group_source_cidrs"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file" hcl:"user_data_file"`
|
||||
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter" hcl:"vpc_filter"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"`
|
||||
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout" hcl:"windows_password_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
|
||||
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
|
||||
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"`
|
||||
SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"`
|
||||
SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"`
|
||||
WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
||||
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface" hcl:"ssh_interface"`
|
||||
SessionManagerPort *int `mapstructure:"session_manager_port" cty:"session_manager_port" hcl:"session_manager_port"`
|
||||
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings" hcl:"ami_block_device_mappings"`
|
||||
LaunchMappings []common.FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings" hcl:"launch_block_device_mappings"`
|
||||
AccountId *string `mapstructure:"account_id" required:"true" cty:"account_id" hcl:"account_id"`
|
||||
BundleDestination *string `mapstructure:"bundle_destination" required:"false" cty:"bundle_destination" hcl:"bundle_destination"`
|
||||
BundlePrefix *string `mapstructure:"bundle_prefix" required:"false" cty:"bundle_prefix" hcl:"bundle_prefix"`
|
||||
BundleUploadCommand *string `mapstructure:"bundle_upload_command" required:"false" cty:"bundle_upload_command" hcl:"bundle_upload_command"`
|
||||
BundleVolCommand *string `mapstructure:"bundle_vol_command" required:"false" cty:"bundle_vol_command" hcl:"bundle_vol_command"`
|
||||
S3Bucket *string `mapstructure:"s3_bucket" required:"true" cty:"s3_bucket" hcl:"s3_bucket"`
|
||||
X509CertPath *string `mapstructure:"x509_cert_path" required:"true" cty:"x509_cert_path" hcl:"x509_cert_path"`
|
||||
X509KeyPath *string `mapstructure:"x509_key_path" required:"true" cty:"x509_key_path" hcl:"x509_key_path"`
|
||||
X509UploadPath *string `mapstructure:"x509_upload_path" required:"false" cty:"x509_upload_path" hcl:"x509_upload_path"`
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
|
||||
AccessKey *string `mapstructure:"access_key" required:"true" cty:"access_key"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
|
||||
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
|
||||
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
|
||||
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
|
||||
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
|
||||
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
|
||||
SecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
|
||||
SkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
|
||||
SkipMetadataApiCheck *bool `mapstructure:"skip_metadata_api_check" cty:"skip_metadata_api_check"`
|
||||
Token *string `mapstructure:"token" required:"false" cty:"token"`
|
||||
VaultAWSEngine *common.FlatVaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false" cty:"vault_aws_engine"`
|
||||
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name"`
|
||||
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description"`
|
||||
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type"`
|
||||
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users"`
|
||||
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups"`
|
||||
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes"`
|
||||
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions"`
|
||||
AMITags map[string]string `mapstructure:"tags" required:"false" cty:"tags"`
|
||||
AMITag []hcl2template.FlatNameValue `mapstructure:"tag" required:"false" cty:"tag"`
|
||||
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
|
||||
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
|
||||
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
|
||||
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
|
||||
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
|
||||
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
|
||||
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
|
||||
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
|
||||
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
|
||||
SnapshotTag []hcl2template.FlatNameValue `mapstructure:"snapshot_tag" required:"false" cty:"snapshot_tag"`
|
||||
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
|
||||
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address"`
|
||||
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone"`
|
||||
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes"`
|
||||
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
|
||||
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
|
||||
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
|
||||
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
|
||||
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
|
||||
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
|
||||
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
|
||||
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
|
||||
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter"`
|
||||
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags"`
|
||||
RunTag []hcl2template.FlatNameValue `mapstructure:"run_tag" required:"false" cty:"run_tag"`
|
||||
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
|
||||
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
|
||||
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
|
||||
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
|
||||
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
|
||||
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
|
||||
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
|
||||
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
|
||||
SpotTag []hcl2template.FlatNameValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag"`
|
||||
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
|
||||
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
|
||||
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
|
||||
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
|
||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
|
||||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
|
||||
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
|
||||
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
|
||||
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
||||
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
|
||||
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"`
|
||||
LaunchMappings []common.FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings"`
|
||||
AccountId *string `mapstructure:"account_id" required:"true" cty:"account_id"`
|
||||
BundleDestination *string `mapstructure:"bundle_destination" required:"false" cty:"bundle_destination"`
|
||||
BundlePrefix *string `mapstructure:"bundle_prefix" required:"false" cty:"bundle_prefix"`
|
||||
BundleUploadCommand *string `mapstructure:"bundle_upload_command" required:"false" cty:"bundle_upload_command"`
|
||||
BundleVolCommand *string `mapstructure:"bundle_vol_command" required:"false" cty:"bundle_vol_command"`
|
||||
S3Bucket *string `mapstructure:"s3_bucket" required:"true" cty:"s3_bucket"`
|
||||
X509CertPath *string `mapstructure:"x509_cert_path" required:"true" cty:"x509_cert_path"`
|
||||
X509KeyPath *string `mapstructure:"x509_key_path" required:"true" cty:"x509_key_path"`
|
||||
X509UploadPath *string `mapstructure:"x509_upload_path" required:"false" cty:"x509_upload_path"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
@@ -185,7 +178,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},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
|
||||
@@ -195,7 +188,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"snapshot_tag": &hcldec.BlockListSpec{TypeName: "snapshot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
|
||||
@@ -211,7 +204,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "run_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"run_tag": &hcldec.BlockListSpec{TypeName: "run_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
|
||||
@@ -220,7 +213,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"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.AttrSpec{Name: "spot_tags", Type: cty.Map(cty.String), Required: false},
|
||||
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
||||
@@ -237,14 +230,10 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
|
||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
||||
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
||||
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
||||
"ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false},
|
||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
||||
@@ -255,7 +244,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
||||
@@ -270,14 +258,12 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
||||
"winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
|
||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
|
||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||
"ssh_interface": &hcldec.AttrSpec{Name: "ssh_interface", Type: cty.String, Required: false},
|
||||
"session_manager_port": &hcldec.AttrSpec{Name: "session_manager_port", Type: cty.Number, Required: false},
|
||||
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
|
||||
"launch_block_device_mappings": &hcldec.BlockListSpec{TypeName: "launch_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
|
||||
"account_id": &hcldec.AttrSpec{Name: "account_id", Type: cty.String, Required: false},
|
||||
|
||||
@@ -134,7 +134,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
}
|
||||
} else {
|
||||
// User is not using Managed Images to build, warning message here that this path is being deprecated
|
||||
ui.Error("Warning: You are using Azure Packer Builder to create VHDs which is being deprecated, consider using Managed Images. Learn more https://www.packer.io/docs/builders/azure/arm#azure-arm-builder-specific-options")
|
||||
ui.Error("Warning: You are using Azure Packer Builder to create VHDs which is being deprecated, consider using Managed Images. Learn more http://aka.ms/packermanagedimage")
|
||||
}
|
||||
|
||||
if b.config.BuildResourceGroupName != "" {
|
||||
|
||||
+15
-58
@@ -103,16 +103,8 @@ type Config struct {
|
||||
// Authentication via OAUTH
|
||||
ClientConfig client.Config `mapstructure:",squash"`
|
||||
|
||||
// If set with one or more resource ids of user assigned managed identities, they will be configured on the VM.
|
||||
// See [documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token)
|
||||
// for how to acquire tokens within the VM.
|
||||
// To assign a user assigned managed identity to a VM, the provided account or service principal must have [Managed Identity Operator](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#managed-identity-operator)
|
||||
// and [Virtual Machine Contributor](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#virtual-machine-contributor) role assignments.
|
||||
UserAssignedManagedIdentities []string `mapstructure:"user_assigned_managed_identities" required:"false"`
|
||||
|
||||
// VHD prefix.
|
||||
CaptureNamePrefix string `mapstructure:"capture_name_prefix"`
|
||||
// Destination container name.
|
||||
// Capture
|
||||
CaptureNamePrefix string `mapstructure:"capture_name_prefix"`
|
||||
CaptureContainerName string `mapstructure:"capture_container_name"`
|
||||
// Use a [Shared Gallery
|
||||
// image](https://azure.microsoft.com/en-us/blog/announcing-the-public-preview-of-shared-image-gallery/)
|
||||
@@ -190,27 +182,25 @@ type Config struct {
|
||||
// CLI example
|
||||
// `az vm image list --location westus --publisher Canonical --offer UbuntuServer --sku 16.04.0-LTS --all`
|
||||
ImageVersion string `mapstructure:"image_version" required:"false"`
|
||||
// URL to a custom VHD to use for your base image. If this value is set,
|
||||
// image_publisher, image_offer, image_sku, or image_version should not be set.
|
||||
// URL to a custom VHD to use for your base image. If this value is set, do
|
||||
// not set image_publisher, image_offer, image_sku, or image_version.
|
||||
ImageUrl string `mapstructure:"image_url" required:"true"`
|
||||
// Name of a custom managed image to use for your base image. If this value is set, do
|
||||
// not set image_publisher, image_offer, image_sku, or image_version.
|
||||
// If this value is set, the option
|
||||
// If this value is set, the value
|
||||
// `custom_managed_image_resource_group_name` must also be set. See
|
||||
// [documentation](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview#images)
|
||||
// to learn more about managed images.
|
||||
CustomManagedImageName string `mapstructure:"custom_managed_image_name" required:"true"`
|
||||
|
||||
// Name of a custom managed image's resource group to use for your base image. If this
|
||||
// value is set, image_publisher, image_offer, image_sku, or image_version should not be set.
|
||||
// If this value is set, the option
|
||||
// value is set, image_publisher, image_offer, image_sku, or image_version.
|
||||
// `custom_managed_image_name` must also be set. See
|
||||
// [documentation](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview#images)
|
||||
// to learn more about managed images.
|
||||
CustomManagedImageResourceGroupName string `mapstructure:"custom_managed_image_resource_group_name" required:"true"`
|
||||
customManagedImageID string
|
||||
|
||||
// Azure datacenter in which your VM will build.
|
||||
Location string `mapstructure:"location"`
|
||||
// Size of the VM used for building. This can be changed when you deploy a
|
||||
// VM from your VHD. See
|
||||
@@ -249,10 +239,10 @@ type Config struct {
|
||||
// region that supports [availability
|
||||
// zones](https://docs.microsoft.com/en-us/azure/availability-zones/az-overview).
|
||||
ManagedImageZoneResilient bool `mapstructure:"managed_image_zone_resilient" required:"false"`
|
||||
// Name/value pair tags to apply to every resource deployed i.e. Resource
|
||||
// Group, VM, NIC, VNET, Public IP, KeyVault, etc. The user can define up
|
||||
// to 15 tags. Tag names cannot exceed 512 characters, and tag values
|
||||
// cannot exceed 256 characters.
|
||||
// the user can define up to 15
|
||||
// tags. Tag names cannot exceed 512 characters, and tag values cannot exceed
|
||||
// 256 characters. Tags are applied to every resource deployed by a Packer
|
||||
// build, i.e. Resource Group, VM, NIC, VNET, Public IP, KeyVault, etc.
|
||||
AzureTags map[string]*string `mapstructure:"azure_tags" required:"false"`
|
||||
// Same as [`azure_tags`](#azure_tags) but defined as a singular repeatable block
|
||||
// containing a `name` and a `value` field. In HCL2 mode the
|
||||
@@ -340,12 +330,10 @@ type Config struct {
|
||||
// tags to the image to ensure this information is not lost. The following
|
||||
// tags are added.
|
||||
//
|
||||
// ```text
|
||||
// 1. PlanName
|
||||
// 2. PlanProduct
|
||||
// 3. PlanPublisher
|
||||
// 4. PlanPromotionCode
|
||||
// ```
|
||||
//
|
||||
PlanInfo PlanInformation `mapstructure:"plan_info" required:"false"`
|
||||
// The default PollingDuration for azure is 15mins, this property will override
|
||||
@@ -401,7 +389,7 @@ type Config struct {
|
||||
// see [here](https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/boot-diagnostics) for more info
|
||||
BootDiagSTGAccount string `mapstructure:"boot_diag_storage_account" required:"false"`
|
||||
|
||||
// specify custom azure resource names during build limited to max 10 characters
|
||||
// specify custom azure resource names during build limited to max 10 charcters
|
||||
// this will set the prefix for the resources. The actuall resource names will be
|
||||
// `custom_resource_build_prefix` + resourcetype + 5 character random alphanumeric string
|
||||
CustomResourcePrefix string `mapstructure:"custom_resource_build_prefix" required:"false"`
|
||||
@@ -675,7 +663,7 @@ func setRuntimeValues(c *Config) {
|
||||
c.tmpNicName = tempName.NicName
|
||||
c.tmpPublicIPAddressName = tempName.PublicIPAddressName
|
||||
c.tmpOSDiskName = tempName.OSDiskName
|
||||
c.tmpDataDiskName = tempName.DataDiskName
|
||||
c.tmpDataDiskName = tempName.DataDiskname
|
||||
c.tmpSubnetName = tempName.SubnetName
|
||||
c.tmpVirtualNetworkName = tempName.VirtualNetworkName
|
||||
c.tmpNsgName = tempName.NsgName
|
||||
@@ -683,40 +671,27 @@ func setRuntimeValues(c *Config) {
|
||||
}
|
||||
|
||||
func setUserNamePassword(c *Config) error {
|
||||
// Set default credentials generated by the builder
|
||||
c.UserName = DefaultUserName
|
||||
c.Password = c.tmpAdminPassword
|
||||
|
||||
// Set communicator specific credentials and update defaults if different.
|
||||
// Communicator specific credentials need to be updated as the standard Packer
|
||||
// SSHConfigFunc and WinRMConfigFunc use communicator specific credentials, unless overwritten.
|
||||
|
||||
// SSH comm
|
||||
if c.Comm.SSHUsername == "" {
|
||||
c.Comm.SSHUsername = c.UserName
|
||||
c.Comm.SSHUsername = DefaultUserName
|
||||
}
|
||||
c.UserName = c.Comm.SSHUsername
|
||||
|
||||
// if user has an explicit wish to use an SSH password, we'll set it
|
||||
if c.Comm.SSHPassword != "" {
|
||||
c.Password = c.Comm.SSHPassword
|
||||
}
|
||||
|
||||
if c.Comm.Type == "ssh" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WinRM comm
|
||||
if c.Comm.WinRMUser == "" {
|
||||
c.Comm.WinRMUser = c.UserName
|
||||
c.Comm.WinRMUser = DefaultUserName
|
||||
}
|
||||
c.UserName = c.Comm.WinRMUser
|
||||
|
||||
if c.Comm.WinRMPassword == "" {
|
||||
// Configure password settings using Azure generated credentials
|
||||
c.Comm.WinRMPassword = c.Password
|
||||
c.Comm.WinRMPassword = c.tmpAdminPassword
|
||||
}
|
||||
|
||||
if !isValidPassword(c.Comm.WinRMPassword) {
|
||||
return fmt.Errorf("The supplied \"winrm_password\" must be between 8-123 characters long and must satisfy at least 3 from the following: \n1) Contains an uppercase character \n2) Contains a lowercase character\n3) Contains a numeric digit\n4) Contains a special character\n5) Control characters are not allowed")
|
||||
}
|
||||
@@ -781,24 +756,6 @@ func assertTagProperties(c *Config, errs *packer.MultiError) {
|
||||
func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
|
||||
c.ClientConfig.Validate(errs)
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Identity
|
||||
if len(c.UserAssignedManagedIdentities) != 0 {
|
||||
for _, rid := range c.UserAssignedManagedIdentities {
|
||||
r, err := client.ParseResourceID(rid)
|
||||
if err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, err)
|
||||
} else {
|
||||
if !strings.EqualFold(r.Provider, "Microsoft.ManagedIdentity") {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("A valid user assigned managed identity resource id must have a correct resource provider"))
|
||||
}
|
||||
if !strings.EqualFold(r.ResourceType.String(), "userAssignedIdentities") {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("A valid user assigned managed identity resource id must have a correct resource type"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Capture
|
||||
if c.CaptureContainerName == "" && c.ManagedImageName == "" {
|
||||
|
||||
@@ -10,116 +10,109 @@ 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" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
CloudEnvironmentName *string `mapstructure:"cloud_environment_name" required:"false" cty:"cloud_environment_name" hcl:"cloud_environment_name"`
|
||||
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
||||
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
||||
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
||||
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
||||
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
||||
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
||||
SubscriptionID *string `mapstructure:"subscription_id" cty:"subscription_id" hcl:"subscription_id"`
|
||||
UserAssignedManagedIdentities []string `mapstructure:"user_assigned_managed_identities" required:"false" cty:"user_assigned_managed_identities" hcl:"user_assigned_managed_identities"`
|
||||
CaptureNamePrefix *string `mapstructure:"capture_name_prefix" cty:"capture_name_prefix" hcl:"capture_name_prefix"`
|
||||
CaptureContainerName *string `mapstructure:"capture_container_name" cty:"capture_container_name" hcl:"capture_container_name"`
|
||||
SharedGallery *FlatSharedImageGallery `mapstructure:"shared_image_gallery" required:"false" cty:"shared_image_gallery" hcl:"shared_image_gallery"`
|
||||
SharedGalleryDestination *FlatSharedImageGalleryDestination `mapstructure:"shared_image_gallery_destination" cty:"shared_image_gallery_destination" hcl:"shared_image_gallery_destination"`
|
||||
SharedGalleryTimeout *string `mapstructure:"shared_image_gallery_timeout" cty:"shared_image_gallery_timeout" hcl:"shared_image_gallery_timeout"`
|
||||
SharedGalleryImageVersionEndOfLifeDate *string `mapstructure:"shared_gallery_image_version_end_of_life_date" required:"false" cty:"shared_gallery_image_version_end_of_life_date" hcl:"shared_gallery_image_version_end_of_life_date"`
|
||||
SharedGalleryImageVersionReplicaCount *int32 `mapstructure:"shared_image_gallery_replica_count" required:"false" cty:"shared_image_gallery_replica_count" hcl:"shared_image_gallery_replica_count"`
|
||||
SharedGalleryImageVersionExcludeFromLatest *bool `mapstructure:"shared_gallery_image_version_exclude_from_latest" required:"false" cty:"shared_gallery_image_version_exclude_from_latest" hcl:"shared_gallery_image_version_exclude_from_latest"`
|
||||
ImagePublisher *string `mapstructure:"image_publisher" required:"true" cty:"image_publisher" hcl:"image_publisher"`
|
||||
ImageOffer *string `mapstructure:"image_offer" required:"true" cty:"image_offer" hcl:"image_offer"`
|
||||
ImageSku *string `mapstructure:"image_sku" required:"true" cty:"image_sku" hcl:"image_sku"`
|
||||
ImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version" hcl:"image_version"`
|
||||
ImageUrl *string `mapstructure:"image_url" required:"true" cty:"image_url" hcl:"image_url"`
|
||||
CustomManagedImageName *string `mapstructure:"custom_managed_image_name" required:"true" cty:"custom_managed_image_name" hcl:"custom_managed_image_name"`
|
||||
CustomManagedImageResourceGroupName *string `mapstructure:"custom_managed_image_resource_group_name" required:"true" cty:"custom_managed_image_resource_group_name" hcl:"custom_managed_image_resource_group_name"`
|
||||
Location *string `mapstructure:"location" cty:"location" hcl:"location"`
|
||||
VMSize *string `mapstructure:"vm_size" required:"false" cty:"vm_size" hcl:"vm_size"`
|
||||
ManagedImageResourceGroupName *string `mapstructure:"managed_image_resource_group_name" cty:"managed_image_resource_group_name" hcl:"managed_image_resource_group_name"`
|
||||
ManagedImageName *string `mapstructure:"managed_image_name" cty:"managed_image_name" hcl:"managed_image_name"`
|
||||
ManagedImageStorageAccountType *string `mapstructure:"managed_image_storage_account_type" required:"false" cty:"managed_image_storage_account_type" hcl:"managed_image_storage_account_type"`
|
||||
ManagedImageOSDiskSnapshotName *string `mapstructure:"managed_image_os_disk_snapshot_name" required:"false" cty:"managed_image_os_disk_snapshot_name" hcl:"managed_image_os_disk_snapshot_name"`
|
||||
ManagedImageDataDiskSnapshotPrefix *string `mapstructure:"managed_image_data_disk_snapshot_prefix" required:"false" cty:"managed_image_data_disk_snapshot_prefix" hcl:"managed_image_data_disk_snapshot_prefix"`
|
||||
ManagedImageZoneResilient *bool `mapstructure:"managed_image_zone_resilient" required:"false" cty:"managed_image_zone_resilient" hcl:"managed_image_zone_resilient"`
|
||||
AzureTags map[string]*string `mapstructure:"azure_tags" required:"false" cty:"azure_tags" hcl:"azure_tags"`
|
||||
AzureTag []hcl2template.FlatNameValue `mapstructure:"azure_tag" required:"false" cty:"azure_tag" hcl:"azure_tag"`
|
||||
ResourceGroupName *string `mapstructure:"resource_group_name" cty:"resource_group_name" hcl:"resource_group_name"`
|
||||
StorageAccount *string `mapstructure:"storage_account" cty:"storage_account" hcl:"storage_account"`
|
||||
TempComputeName *string `mapstructure:"temp_compute_name" required:"false" cty:"temp_compute_name" hcl:"temp_compute_name"`
|
||||
TempResourceGroupName *string `mapstructure:"temp_resource_group_name" cty:"temp_resource_group_name" hcl:"temp_resource_group_name"`
|
||||
BuildResourceGroupName *string `mapstructure:"build_resource_group_name" cty:"build_resource_group_name" hcl:"build_resource_group_name"`
|
||||
BuildKeyVaultName *string `mapstructure:"build_key_vault_name" cty:"build_key_vault_name" hcl:"build_key_vault_name"`
|
||||
BuildKeyVaultSKU *string `mapstructure:"build_key_vault_sku" cty:"build_key_vault_sku" hcl:"build_key_vault_sku"`
|
||||
PrivateVirtualNetworkWithPublicIp *bool `mapstructure:"private_virtual_network_with_public_ip" required:"false" cty:"private_virtual_network_with_public_ip" hcl:"private_virtual_network_with_public_ip"`
|
||||
VirtualNetworkName *string `mapstructure:"virtual_network_name" required:"false" cty:"virtual_network_name" hcl:"virtual_network_name"`
|
||||
VirtualNetworkSubnetName *string `mapstructure:"virtual_network_subnet_name" required:"false" cty:"virtual_network_subnet_name" hcl:"virtual_network_subnet_name"`
|
||||
VirtualNetworkResourceGroupName *string `mapstructure:"virtual_network_resource_group_name" required:"false" cty:"virtual_network_resource_group_name" hcl:"virtual_network_resource_group_name"`
|
||||
CustomDataFile *string `mapstructure:"custom_data_file" required:"false" cty:"custom_data_file" hcl:"custom_data_file"`
|
||||
PlanInfo *FlatPlanInformation `mapstructure:"plan_info" required:"false" cty:"plan_info" hcl:"plan_info"`
|
||||
PollingDurationTimeout *string `mapstructure:"polling_duration_timeout" required:"false" cty:"polling_duration_timeout" hcl:"polling_duration_timeout"`
|
||||
OSType *string `mapstructure:"os_type" required:"false" cty:"os_type" hcl:"os_type"`
|
||||
OSDiskSizeGB *int32 `mapstructure:"os_disk_size_gb" required:"false" cty:"os_disk_size_gb" hcl:"os_disk_size_gb"`
|
||||
AdditionalDiskSize []int32 `mapstructure:"disk_additional_size" required:"false" cty:"disk_additional_size" hcl:"disk_additional_size"`
|
||||
DiskCachingType *string `mapstructure:"disk_caching_type" required:"false" cty:"disk_caching_type" hcl:"disk_caching_type"`
|
||||
AllowedInboundIpAddresses []string `mapstructure:"allowed_inbound_ip_addresses" cty:"allowed_inbound_ip_addresses" hcl:"allowed_inbound_ip_addresses"`
|
||||
BootDiagSTGAccount *string `mapstructure:"boot_diag_storage_account" required:"false" cty:"boot_diag_storage_account" hcl:"boot_diag_storage_account"`
|
||||
CustomResourcePrefix *string `mapstructure:"custom_resource_build_prefix" required:"false" cty:"custom_resource_build_prefix" hcl:"custom_resource_build_prefix"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
|
||||
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" undocumented:"true" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
|
||||
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
|
||||
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"`
|
||||
SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"`
|
||||
SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"`
|
||||
WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
||||
AsyncResourceGroupDelete *bool `mapstructure:"async_resourcegroup_delete" required:"false" cty:"async_resourcegroup_delete" hcl:"async_resourcegroup_delete"`
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
|
||||
CloudEnvironmentName *string `mapstructure:"cloud_environment_name" required:"false" cty:"cloud_environment_name"`
|
||||
ClientID *string `mapstructure:"client_id" cty:"client_id"`
|
||||
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret"`
|
||||
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path"`
|
||||
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt"`
|
||||
ObjectID *string `mapstructure:"object_id" cty:"object_id"`
|
||||
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id"`
|
||||
SubscriptionID *string `mapstructure:"subscription_id" cty:"subscription_id"`
|
||||
CaptureNamePrefix *string `mapstructure:"capture_name_prefix" cty:"capture_name_prefix"`
|
||||
CaptureContainerName *string `mapstructure:"capture_container_name" cty:"capture_container_name"`
|
||||
SharedGallery *FlatSharedImageGallery `mapstructure:"shared_image_gallery" required:"false" cty:"shared_image_gallery"`
|
||||
SharedGalleryDestination *FlatSharedImageGalleryDestination `mapstructure:"shared_image_gallery_destination" cty:"shared_image_gallery_destination"`
|
||||
SharedGalleryTimeout *string `mapstructure:"shared_image_gallery_timeout" cty:"shared_image_gallery_timeout"`
|
||||
SharedGalleryImageVersionEndOfLifeDate *string `mapstructure:"shared_gallery_image_version_end_of_life_date" required:"false" cty:"shared_gallery_image_version_end_of_life_date"`
|
||||
SharedGalleryImageVersionReplicaCount *int32 `mapstructure:"shared_image_gallery_replica_count" required:"false" cty:"shared_image_gallery_replica_count"`
|
||||
SharedGalleryImageVersionExcludeFromLatest *bool `mapstructure:"shared_gallery_image_version_exclude_from_latest" required:"false" cty:"shared_gallery_image_version_exclude_from_latest"`
|
||||
ImagePublisher *string `mapstructure:"image_publisher" required:"true" cty:"image_publisher"`
|
||||
ImageOffer *string `mapstructure:"image_offer" required:"true" cty:"image_offer"`
|
||||
ImageSku *string `mapstructure:"image_sku" required:"true" cty:"image_sku"`
|
||||
ImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version"`
|
||||
ImageUrl *string `mapstructure:"image_url" required:"true" cty:"image_url"`
|
||||
CustomManagedImageName *string `mapstructure:"custom_managed_image_name" required:"true" cty:"custom_managed_image_name"`
|
||||
CustomManagedImageResourceGroupName *string `mapstructure:"custom_managed_image_resource_group_name" required:"true" cty:"custom_managed_image_resource_group_name"`
|
||||
Location *string `mapstructure:"location" cty:"location"`
|
||||
VMSize *string `mapstructure:"vm_size" required:"false" cty:"vm_size"`
|
||||
ManagedImageResourceGroupName *string `mapstructure:"managed_image_resource_group_name" cty:"managed_image_resource_group_name"`
|
||||
ManagedImageName *string `mapstructure:"managed_image_name" cty:"managed_image_name"`
|
||||
ManagedImageStorageAccountType *string `mapstructure:"managed_image_storage_account_type" required:"false" cty:"managed_image_storage_account_type"`
|
||||
ManagedImageOSDiskSnapshotName *string `mapstructure:"managed_image_os_disk_snapshot_name" required:"false" cty:"managed_image_os_disk_snapshot_name"`
|
||||
ManagedImageDataDiskSnapshotPrefix *string `mapstructure:"managed_image_data_disk_snapshot_prefix" required:"false" cty:"managed_image_data_disk_snapshot_prefix"`
|
||||
ManagedImageZoneResilient *bool `mapstructure:"managed_image_zone_resilient" required:"false" cty:"managed_image_zone_resilient"`
|
||||
AzureTags map[string]*string `mapstructure:"azure_tags" required:"false" cty:"azure_tags"`
|
||||
AzureTag []hcl2template.FlatNameValue `mapstructure:"azure_tag" required:"false" cty:"azure_tag"`
|
||||
ResourceGroupName *string `mapstructure:"resource_group_name" cty:"resource_group_name"`
|
||||
StorageAccount *string `mapstructure:"storage_account" cty:"storage_account"`
|
||||
TempComputeName *string `mapstructure:"temp_compute_name" required:"false" cty:"temp_compute_name"`
|
||||
TempResourceGroupName *string `mapstructure:"temp_resource_group_name" cty:"temp_resource_group_name"`
|
||||
BuildResourceGroupName *string `mapstructure:"build_resource_group_name" cty:"build_resource_group_name"`
|
||||
BuildKeyVaultName *string `mapstructure:"build_key_vault_name" cty:"build_key_vault_name"`
|
||||
BuildKeyVaultSKU *string `mapstructure:"build_key_vault_sku" cty:"build_key_vault_sku"`
|
||||
PrivateVirtualNetworkWithPublicIp *bool `mapstructure:"private_virtual_network_with_public_ip" required:"false" cty:"private_virtual_network_with_public_ip"`
|
||||
VirtualNetworkName *string `mapstructure:"virtual_network_name" required:"false" cty:"virtual_network_name"`
|
||||
VirtualNetworkSubnetName *string `mapstructure:"virtual_network_subnet_name" required:"false" cty:"virtual_network_subnet_name"`
|
||||
VirtualNetworkResourceGroupName *string `mapstructure:"virtual_network_resource_group_name" required:"false" cty:"virtual_network_resource_group_name"`
|
||||
CustomDataFile *string `mapstructure:"custom_data_file" required:"false" cty:"custom_data_file"`
|
||||
PlanInfo *FlatPlanInformation `mapstructure:"plan_info" required:"false" cty:"plan_info"`
|
||||
PollingDurationTimeout *string `mapstructure:"polling_duration_timeout" required:"false" cty:"polling_duration_timeout"`
|
||||
OSType *string `mapstructure:"os_type" required:"false" cty:"os_type"`
|
||||
OSDiskSizeGB *int32 `mapstructure:"os_disk_size_gb" required:"false" cty:"os_disk_size_gb"`
|
||||
AdditionalDiskSize []int32 `mapstructure:"disk_additional_size" required:"false" cty:"disk_additional_size"`
|
||||
DiskCachingType *string `mapstructure:"disk_caching_type" required:"false" cty:"disk_caching_type"`
|
||||
AllowedInboundIpAddresses []string `mapstructure:"allowed_inbound_ip_addresses" cty:"allowed_inbound_ip_addresses"`
|
||||
BootDiagSTGAccount *string `mapstructure:"boot_diag_storage_account" required:"false" cty:"boot_diag_storage_account"`
|
||||
CustomResourcePrefix *string `mapstructure:"custom_resource_build_prefix" required:"false" cty:"custom_resource_build_prefix"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
|
||||
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" cty:"temporary_key_pair_name"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
|
||||
AsyncResourceGroupDelete *bool `mapstructure:"async_resourcegroup_delete" required:"false" cty:"async_resourcegroup_delete"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
@@ -134,116 +127,109 @@ 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.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},
|
||||
"user_assigned_managed_identities": &hcldec.AttrSpec{Name: "user_assigned_managed_identities", Type: cty.List(cty.String), Required: false},
|
||||
"capture_name_prefix": &hcldec.AttrSpec{Name: "capture_name_prefix", Type: cty.String, Required: false},
|
||||
"capture_container_name": &hcldec.AttrSpec{Name: "capture_container_name", Type: cty.String, Required: false},
|
||||
"shared_image_gallery": &hcldec.BlockSpec{TypeName: "shared_image_gallery", Nested: hcldec.ObjectSpec((*FlatSharedImageGallery)(nil).HCL2Spec())},
|
||||
"shared_image_gallery_destination": &hcldec.BlockSpec{TypeName: "shared_image_gallery_destination", Nested: hcldec.ObjectSpec((*FlatSharedImageGalleryDestination)(nil).HCL2Spec())},
|
||||
"shared_image_gallery_timeout": &hcldec.AttrSpec{Name: "shared_image_gallery_timeout", Type: cty.String, Required: false},
|
||||
"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},
|
||||
"capture_name_prefix": &hcldec.AttrSpec{Name: "capture_name_prefix", Type: cty.String, Required: false},
|
||||
"capture_container_name": &hcldec.AttrSpec{Name: "capture_container_name", Type: cty.String, Required: false},
|
||||
"shared_image_gallery": &hcldec.BlockSpec{TypeName: "shared_image_gallery", Nested: hcldec.ObjectSpec((*FlatSharedImageGallery)(nil).HCL2Spec())},
|
||||
"shared_image_gallery_destination": &hcldec.BlockSpec{TypeName: "shared_image_gallery_destination", Nested: hcldec.ObjectSpec((*FlatSharedImageGalleryDestination)(nil).HCL2Spec())},
|
||||
"shared_image_gallery_timeout": &hcldec.AttrSpec{Name: "shared_image_gallery_timeout", Type: cty.String, Required: false},
|
||||
"shared_gallery_image_version_end_of_life_date": &hcldec.AttrSpec{Name: "shared_gallery_image_version_end_of_life_date", Type: cty.String, Required: false},
|
||||
"shared_image_gallery_replica_count": &hcldec.AttrSpec{Name: "shared_image_gallery_replica_count", Type: cty.Number, Required: false},
|
||||
"shared_gallery_image_version_exclude_from_latest": &hcldec.AttrSpec{Name: "shared_gallery_image_version_exclude_from_latest", Type: cty.Bool, Required: false},
|
||||
"image_publisher": &hcldec.AttrSpec{Name: "image_publisher", Type: cty.String, Required: false},
|
||||
"image_offer": &hcldec.AttrSpec{Name: "image_offer", Type: cty.String, Required: false},
|
||||
"image_sku": &hcldec.AttrSpec{Name: "image_sku", Type: cty.String, Required: false},
|
||||
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
|
||||
"image_url": &hcldec.AttrSpec{Name: "image_url", Type: cty.String, Required: false},
|
||||
"custom_managed_image_name": &hcldec.AttrSpec{Name: "custom_managed_image_name", Type: cty.String, Required: false},
|
||||
"custom_managed_image_resource_group_name": &hcldec.AttrSpec{Name: "custom_managed_image_resource_group_name", Type: cty.String, Required: false},
|
||||
"location": &hcldec.AttrSpec{Name: "location", Type: cty.String, Required: false},
|
||||
"vm_size": &hcldec.AttrSpec{Name: "vm_size", Type: cty.String, Required: false},
|
||||
"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},
|
||||
"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.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},
|
||||
"temp_compute_name": &hcldec.AttrSpec{Name: "temp_compute_name", Type: cty.String, Required: false},
|
||||
"temp_resource_group_name": &hcldec.AttrSpec{Name: "temp_resource_group_name", Type: cty.String, Required: false},
|
||||
"build_resource_group_name": &hcldec.AttrSpec{Name: "build_resource_group_name", Type: cty.String, Required: false},
|
||||
"build_key_vault_name": &hcldec.AttrSpec{Name: "build_key_vault_name", Type: cty.String, Required: false},
|
||||
"build_key_vault_sku": &hcldec.AttrSpec{Name: "build_key_vault_sku", Type: cty.String, Required: false},
|
||||
"private_virtual_network_with_public_ip": &hcldec.AttrSpec{Name: "private_virtual_network_with_public_ip", Type: cty.Bool, Required: false},
|
||||
"virtual_network_name": &hcldec.AttrSpec{Name: "virtual_network_name", Type: cty.String, Required: false},
|
||||
"virtual_network_subnet_name": &hcldec.AttrSpec{Name: "virtual_network_subnet_name", Type: cty.String, Required: false},
|
||||
"virtual_network_resource_group_name": &hcldec.AttrSpec{Name: "virtual_network_resource_group_name", Type: cty.String, Required: false},
|
||||
"custom_data_file": &hcldec.AttrSpec{Name: "custom_data_file", Type: cty.String, Required: false},
|
||||
"plan_info": &hcldec.BlockSpec{TypeName: "plan_info", Nested: hcldec.ObjectSpec((*FlatPlanInformation)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"os_disk_size_gb": &hcldec.AttrSpec{Name: "os_disk_size_gb", Type: cty.Number, Required: false},
|
||||
"disk_additional_size": &hcldec.AttrSpec{Name: "disk_additional_size", Type: cty.List(cty.Number), Required: false},
|
||||
"disk_caching_type": &hcldec.AttrSpec{Name: "disk_caching_type", Type: cty.String, Required: false},
|
||||
"allowed_inbound_ip_addresses": &hcldec.AttrSpec{Name: "allowed_inbound_ip_addresses", Type: cty.List(cty.String), Required: false},
|
||||
"boot_diag_storage_account": &hcldec.AttrSpec{Name: "boot_diag_storage_account", Type: cty.String, Required: false},
|
||||
"custom_resource_build_prefix": &hcldec.AttrSpec{Name: "custom_resource_build_prefix", Type: cty.String, Required: false},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
|
||||
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
|
||||
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
|
||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
||||
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
||||
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
||||
"ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false},
|
||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
||||
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
|
||||
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
|
||||
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
|
||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
||||
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
|
||||
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
|
||||
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
|
||||
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
|
||||
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
|
||||
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
|
||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
||||
"winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
|
||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
|
||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||
"async_resourcegroup_delete": &hcldec.AttrSpec{Name: "async_resourcegroup_delete", Type: cty.Bool, Required: false},
|
||||
"image_publisher": &hcldec.AttrSpec{Name: "image_publisher", Type: cty.String, Required: false},
|
||||
"image_offer": &hcldec.AttrSpec{Name: "image_offer", Type: cty.String, Required: false},
|
||||
"image_sku": &hcldec.AttrSpec{Name: "image_sku", Type: cty.String, Required: false},
|
||||
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
|
||||
"image_url": &hcldec.AttrSpec{Name: "image_url", Type: cty.String, Required: false},
|
||||
"custom_managed_image_name": &hcldec.AttrSpec{Name: "custom_managed_image_name", Type: cty.String, Required: false},
|
||||
"custom_managed_image_resource_group_name": &hcldec.AttrSpec{Name: "custom_managed_image_resource_group_name", Type: cty.String, Required: false},
|
||||
"location": &hcldec.AttrSpec{Name: "location", Type: cty.String, Required: false},
|
||||
"vm_size": &hcldec.AttrSpec{Name: "vm_size", Type: cty.String, Required: false},
|
||||
"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},
|
||||
"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.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},
|
||||
"temp_compute_name": &hcldec.AttrSpec{Name: "temp_compute_name", Type: cty.String, Required: false},
|
||||
"temp_resource_group_name": &hcldec.AttrSpec{Name: "temp_resource_group_name", Type: cty.String, Required: false},
|
||||
"build_resource_group_name": &hcldec.AttrSpec{Name: "build_resource_group_name", Type: cty.String, Required: false},
|
||||
"build_key_vault_name": &hcldec.AttrSpec{Name: "build_key_vault_name", Type: cty.String, Required: false},
|
||||
"build_key_vault_sku": &hcldec.AttrSpec{Name: "build_key_vault_sku", Type: cty.String, Required: false},
|
||||
"private_virtual_network_with_public_ip": &hcldec.AttrSpec{Name: "private_virtual_network_with_public_ip", Type: cty.Bool, Required: false},
|
||||
"virtual_network_name": &hcldec.AttrSpec{Name: "virtual_network_name", Type: cty.String, Required: false},
|
||||
"virtual_network_subnet_name": &hcldec.AttrSpec{Name: "virtual_network_subnet_name", Type: cty.String, Required: false},
|
||||
"virtual_network_resource_group_name": &hcldec.AttrSpec{Name: "virtual_network_resource_group_name", Type: cty.String, Required: false},
|
||||
"custom_data_file": &hcldec.AttrSpec{Name: "custom_data_file", Type: cty.String, Required: false},
|
||||
"plan_info": &hcldec.BlockSpec{TypeName: "plan_info", Nested: hcldec.ObjectSpec((*FlatPlanInformation)(nil).HCL2Spec())},
|
||||
"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},
|
||||
"os_disk_size_gb": &hcldec.AttrSpec{Name: "os_disk_size_gb", Type: cty.Number, Required: false},
|
||||
"disk_additional_size": &hcldec.AttrSpec{Name: "disk_additional_size", Type: cty.List(cty.Number), Required: false},
|
||||
"disk_caching_type": &hcldec.AttrSpec{Name: "disk_caching_type", Type: cty.String, Required: false},
|
||||
"allowed_inbound_ip_addresses": &hcldec.AttrSpec{Name: "allowed_inbound_ip_addresses", Type: cty.List(cty.String), Required: false},
|
||||
"boot_diag_storage_account": &hcldec.AttrSpec{Name: "boot_diag_storage_account", Type: cty.String, Required: false},
|
||||
"custom_resource_build_prefix": &hcldec.AttrSpec{Name: "custom_resource_build_prefix", Type: cty.String, Required: false},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
|
||||
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
|
||||
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
|
||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
||||
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
|
||||
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
|
||||
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
|
||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
||||
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
|
||||
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
|
||||
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
|
||||
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
|
||||
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
|
||||
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
|
||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
|
||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||
"async_resourcegroup_delete": &hcldec.AttrSpec{Name: "async_resourcegroup_delete", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -251,10 +237,10 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
// FlatPlanInformation is an auto-generated flat version of PlanInformation.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatPlanInformation struct {
|
||||
PlanName *string `mapstructure:"plan_name" cty:"plan_name" hcl:"plan_name"`
|
||||
PlanProduct *string `mapstructure:"plan_product" cty:"plan_product" hcl:"plan_product"`
|
||||
PlanPublisher *string `mapstructure:"plan_publisher" cty:"plan_publisher" hcl:"plan_publisher"`
|
||||
PlanPromotionCode *string `mapstructure:"plan_promotion_code" cty:"plan_promotion_code" hcl:"plan_promotion_code"`
|
||||
PlanName *string `mapstructure:"plan_name" cty:"plan_name"`
|
||||
PlanProduct *string `mapstructure:"plan_product" cty:"plan_product"`
|
||||
PlanPublisher *string `mapstructure:"plan_publisher" cty:"plan_publisher"`
|
||||
PlanPromotionCode *string `mapstructure:"plan_promotion_code" cty:"plan_promotion_code"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatPlanInformation.
|
||||
@@ -280,11 +266,11 @@ func (*FlatPlanInformation) HCL2Spec() map[string]hcldec.Spec {
|
||||
// FlatSharedImageGallery is an auto-generated flat version of SharedImageGallery.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatSharedImageGallery struct {
|
||||
Subscription *string `mapstructure:"subscription" cty:"subscription" hcl:"subscription"`
|
||||
ResourceGroup *string `mapstructure:"resource_group" cty:"resource_group" hcl:"resource_group"`
|
||||
GalleryName *string `mapstructure:"gallery_name" cty:"gallery_name" hcl:"gallery_name"`
|
||||
ImageName *string `mapstructure:"image_name" cty:"image_name" hcl:"image_name"`
|
||||
ImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version" hcl:"image_version"`
|
||||
Subscription *string `mapstructure:"subscription" cty:"subscription"`
|
||||
ResourceGroup *string `mapstructure:"resource_group" cty:"resource_group"`
|
||||
GalleryName *string `mapstructure:"gallery_name" cty:"gallery_name"`
|
||||
ImageName *string `mapstructure:"image_name" cty:"image_name"`
|
||||
ImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatSharedImageGallery.
|
||||
@@ -311,11 +297,11 @@ func (*FlatSharedImageGallery) HCL2Spec() map[string]hcldec.Spec {
|
||||
// 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 {
|
||||
SigDestinationResourceGroup *string `mapstructure:"resource_group" cty:"resource_group" hcl:"resource_group"`
|
||||
SigDestinationGalleryName *string `mapstructure:"gallery_name" cty:"gallery_name" hcl:"gallery_name"`
|
||||
SigDestinationImageName *string `mapstructure:"image_name" cty:"image_name" hcl:"image_name"`
|
||||
SigDestinationImageVersion *string `mapstructure:"image_version" cty:"image_version" hcl:"image_version"`
|
||||
SigDestinationReplicationRegions []string `mapstructure:"replication_regions" cty:"replication_regions" hcl:"replication_regions"`
|
||||
SigDestinationResourceGroup *string `mapstructure:"resource_group" cty:"resource_group"`
|
||||
SigDestinationGalleryName *string `mapstructure:"gallery_name" cty:"gallery_name"`
|
||||
SigDestinationImageName *string `mapstructure:"image_name" cty:"image_name"`
|
||||
SigDestinationImageVersion *string `mapstructure:"image_version" cty:"image_version"`
|
||||
SigDestinationReplicationRegions []string `mapstructure:"replication_regions" cty:"replication_regions"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatSharedImageGalleryDestination.
|
||||
|
||||
@@ -55,54 +55,6 @@ func TestConfigShouldProvideReasonableDefaultValues(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigUserNameOverride(t *testing.T) {
|
||||
builderValues := getArmBuilderConfiguration()
|
||||
builderValues["ssh_username"] = "override_username"
|
||||
builderValues["communicator"] = "ssh"
|
||||
|
||||
var c Config
|
||||
_, err := c.Prepare(builderValues, getPackerConfiguration())
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("newConfig failed: %s", err)
|
||||
}
|
||||
|
||||
// SSH comm
|
||||
if c.Password != c.tmpAdminPassword {
|
||||
t.Errorf("Expected 'Password' to be set to generated password, but found %q!", c.Password)
|
||||
}
|
||||
if c.Comm.SSHPassword != "" {
|
||||
t.Errorf("Expected 'c.Comm.SSHPassword' to be empty, but found %q!", c.Comm.SSHPassword)
|
||||
}
|
||||
if c.UserName != "override_username" {
|
||||
t.Errorf("Expected 'UserName' to be set to 'override_username', but found %q!", c.UserName)
|
||||
}
|
||||
if c.Comm.SSHUsername != "override_username" {
|
||||
t.Errorf("Expected 'c.Comm.SSHUsername' to be set to 'override_username', but found %q!", c.Comm.SSHUsername)
|
||||
}
|
||||
|
||||
// Winrm comm
|
||||
c = Config{}
|
||||
builderValues = getArmBuilderConfiguration()
|
||||
builderValues["communicator"] = "winrm"
|
||||
builderValues["winrm_username"] = "override_winrm_username"
|
||||
_, err = c.Prepare(builderValues, getPackerConfiguration())
|
||||
if err != nil {
|
||||
t.Fatalf("newConfig failed: %s", err)
|
||||
}
|
||||
if c.Password != c.tmpAdminPassword {
|
||||
t.Errorf("Expected 'Password' to be set to generated password, but found %q!", c.Password)
|
||||
}
|
||||
if c.Comm.WinRMPassword != c.tmpAdminPassword {
|
||||
t.Errorf("Expected 'c.Comm.WinRMPassword' to be set to generated password, but found %q!", c.Comm.WinRMPassword)
|
||||
}
|
||||
if c.UserName != "override_winrm_username" {
|
||||
t.Errorf("Expected 'UserName' to be set to 'override_winrm_username', but found %q!", c.UserName)
|
||||
}
|
||||
if c.Comm.WinRMUser != "override_winrm_username" {
|
||||
t.Errorf("Expected 'c.Comm.WinRMUser' to be set to 'override_winrm_username', but found %q!", c.Comm.WinRMUser)
|
||||
}
|
||||
}
|
||||
func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) {
|
||||
builderValues := getArmBuilderConfiguration()
|
||||
builderValues["ssh_password"] = "override_password"
|
||||
@@ -159,13 +111,13 @@ func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) {
|
||||
t.Errorf("Expected 'Password' to be set to 'Override_winrm_password1', but found %q!", c.Password)
|
||||
}
|
||||
if c.Comm.WinRMPassword != "Override_winrm_password1" {
|
||||
t.Errorf("Expected 'c.Comm.WinRMPassword' to be set to 'Override_winrm_password1', but found %q!", c.Comm.WinRMPassword)
|
||||
t.Errorf("Expected 'c.Comm.WinRMPassword' to be set to 'Override_winrm_password1', but found %q!", c.Comm.SSHPassword)
|
||||
}
|
||||
if c.UserName != "override_winrm_username" {
|
||||
t.Errorf("Expected 'UserName' to be set to 'override_winrm_username', but found %q!", c.UserName)
|
||||
}
|
||||
if c.Comm.WinRMUser != "override_winrm_username" {
|
||||
t.Errorf("Expected 'c.Comm.WinRMUser' to be set to 'override_winrm_username', but found %q!", c.Comm.WinRMUser)
|
||||
t.Errorf("Expected 'c.Comm.WinRMUser' to be set to 'override_winrm_username', but found %q!", c.Comm.SSHUsername)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,10 +548,6 @@ func TestSystemShouldDefineRuntimeValues(t *testing.T) {
|
||||
t.Errorf("Expected tmpOSDiskName to not be empty, but it was '%s'!", c.tmpOSDiskName)
|
||||
}
|
||||
|
||||
if c.tmpDataDiskName == "" {
|
||||
t.Errorf("Expected tmpDataDiskName to not be empty, but it was '%s'!", c.tmpDataDiskName)
|
||||
}
|
||||
|
||||
if c.tmpNsgName == "" {
|
||||
t.Errorf("Expected tmpNsgName to not be empty, but it was '%s'!", c.tmpNsgName)
|
||||
}
|
||||
@@ -2092,49 +2040,3 @@ func getPackerCommunicatorConfiguration() map[string]string {
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
func getPackerSSHPasswordCommunicatorConfiguration() map[string]string {
|
||||
config := map[string]string{
|
||||
"ssh_password": "superS3cret",
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
func TestConfigShouldRejectMalformedUserAssignedManagedIdentities(t *testing.T) {
|
||||
config := map[string]interface{}{
|
||||
"capture_name_prefix": "ignore",
|
||||
"capture_container_name": "ignore",
|
||||
"image_offer": "ignore",
|
||||
"image_publisher": "ignore",
|
||||
"image_sku": "ignore",
|
||||
"location": "ignore",
|
||||
"storage_account": "ignore",
|
||||
"resource_group_name": "ignore",
|
||||
"subscription_id": "ignore",
|
||||
"communicator": "none",
|
||||
// Does not matter for this test case, just pick one.
|
||||
"os_type": constants.Target_Linux,
|
||||
}
|
||||
|
||||
config["user_assigned_managed_identities"] = []string{"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id"}
|
||||
var c Config
|
||||
if _, err := c.Prepare(config, getPackerConfiguration()); err != nil {
|
||||
t.Error("Expected test to pass, but it failed with the well-formed user_assigned_managed_identities.")
|
||||
}
|
||||
|
||||
malformedUserAssignedManagedIdentityResourceIds := []string{
|
||||
"not_a_resource_id",
|
||||
"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/",
|
||||
"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Compute/images/im",
|
||||
"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.ManagedIdentity/userAssignedIdentitie/id",
|
||||
}
|
||||
|
||||
for _, x := range malformedUserAssignedManagedIdentityResourceIds {
|
||||
config["user_assigned_managed_identities"] = x
|
||||
var c Config
|
||||
if _, err := c.Prepare(config, getPackerConfiguration()); err == nil {
|
||||
t.Errorf("Expected test to fail, but it succeeded with the malformed user_assigned_managed_identities set to %q.", x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,34 +55,16 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error)
|
||||
|
||||
switch config.OSType {
|
||||
case constants.Target_Linux:
|
||||
err = builder.BuildLinux(config.sshAuthorizedKey, config.Comm.SSHPassword == "") // if ssh password is not explicitly specified, disable password auth
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.BuildLinux(config.sshAuthorizedKey)
|
||||
case constants.Target_Windows:
|
||||
osType = compute.Windows
|
||||
err = builder.BuildWindows(config.tmpKeyVaultName, config.tmpWinRMCertificateUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(config.UserAssignedManagedIdentities) != 0 {
|
||||
if err := builder.SetIdentity(config.UserAssignedManagedIdentities); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.BuildWindows(config.tmpKeyVaultName, config.tmpWinRMCertificateUrl)
|
||||
}
|
||||
|
||||
if config.ImageUrl != "" {
|
||||
err = builder.SetImageUrl(config.ImageUrl, osType, config.diskCachingType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.SetImageUrl(config.ImageUrl, osType, config.diskCachingType)
|
||||
} else if config.CustomManagedImageName != "" {
|
||||
err = builder.SetManagedDiskUrl(config.customManagedImageID, config.managedImageStorageAccountType, config.diskCachingType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.SetManagedDiskUrl(config.customManagedImageID, config.managedImageStorageAccountType, config.diskCachingType)
|
||||
} else if config.ManagedImageName != "" && config.ImagePublisher != "" {
|
||||
imageID := fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Compute/locations/%s/publishers/%s/ArtifactTypes/vmimage/offers/%s/skus/%s/versions/%s",
|
||||
config.ClientConfig.SubscriptionID,
|
||||
@@ -104,62 +86,38 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error)
|
||||
config.SharedGallery.ImageVersion)
|
||||
}
|
||||
|
||||
err = builder.SetSharedGalleryImage(config.Location, imageID, config.diskCachingType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.SetSharedGalleryImage(config.Location, imageID, config.diskCachingType)
|
||||
} else {
|
||||
err = builder.SetMarketPlaceImage(config.ImagePublisher, config.ImageOffer, config.ImageSku, config.ImageVersion, config.diskCachingType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.SetMarketPlaceImage(config.ImagePublisher, config.ImageOffer, config.ImageSku, config.ImageVersion, config.diskCachingType)
|
||||
}
|
||||
|
||||
if config.OSDiskSizeGB > 0 {
|
||||
err = builder.SetOSDiskSizeGB(config.OSDiskSizeGB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.SetOSDiskSizeGB(config.OSDiskSizeGB)
|
||||
}
|
||||
|
||||
if len(config.AdditionalDiskSize) > 0 {
|
||||
isManaged := config.CustomManagedImageName != "" || (config.ManagedImageName != "" && config.ImagePublisher != "") || config.SharedGallery.Subscription != ""
|
||||
err = builder.SetAdditionalDisks(config.AdditionalDiskSize, config.tmpDataDiskName, isManaged, config.diskCachingType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.SetAdditionalDisks(config.AdditionalDiskSize, config.tmpDataDiskName, isManaged, config.diskCachingType)
|
||||
}
|
||||
|
||||
if config.customData != "" {
|
||||
err = builder.SetCustomData(config.customData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.SetCustomData(config.customData)
|
||||
}
|
||||
|
||||
if config.PlanInfo.PlanName != "" {
|
||||
err = builder.SetPlanInfo(config.PlanInfo.PlanName, config.PlanInfo.PlanProduct, config.PlanInfo.PlanPublisher, config.PlanInfo.PlanPromotionCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.SetPlanInfo(config.PlanInfo.PlanName, config.PlanInfo.PlanProduct, config.PlanInfo.PlanPublisher, config.PlanInfo.PlanPromotionCode)
|
||||
}
|
||||
|
||||
if config.VirtualNetworkName != "" && DefaultPrivateVirtualNetworkWithPublicIp != config.PrivateVirtualNetworkWithPublicIp {
|
||||
err = builder.SetPrivateVirtualNetworkWithPublicIp(
|
||||
builder.SetPrivateVirtualNetworkWithPublicIp(
|
||||
config.VirtualNetworkResourceGroupName,
|
||||
config.VirtualNetworkName,
|
||||
config.VirtualNetworkSubnetName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if config.VirtualNetworkName != "" {
|
||||
err = builder.SetVirtualNetwork(
|
||||
builder.SetVirtualNetwork(
|
||||
config.VirtualNetworkResourceGroupName,
|
||||
config.VirtualNetworkName,
|
||||
config.VirtualNetworkSubnetName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if config.AllowedInboundIpAddresses != nil && len(config.AllowedInboundIpAddresses) >= 1 && config.Comm.Port() != 0 {
|
||||
@@ -176,11 +134,7 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error)
|
||||
}
|
||||
}
|
||||
|
||||
err = builder.SetTags(&config.AzureTags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
builder.SetTags(&config.AzureTags)
|
||||
doc, _ := builder.ToJSON()
|
||||
return createDeploymentParameters(*doc, params)
|
||||
}
|
||||
|
||||
@@ -149,10 +149,10 @@
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"disablePasswordAuthentication": true,
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
|
||||
@@ -153,10 +153,10 @@
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"disablePasswordAuthentication": true,
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
|
||||
+1
-1
@@ -126,10 +126,10 @@
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"disablePasswordAuthentication": true,
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
|
||||
+1
-1
@@ -141,10 +141,10 @@
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"disablePasswordAuthentication": true,
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
|
||||
+1
-1
@@ -126,10 +126,10 @@
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"disablePasswordAuthentication": true,
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
|
||||
+1
-1
@@ -104,10 +104,10 @@
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"disablePasswordAuthentication": true,
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@
|
||||
"lun": 0,
|
||||
"name": "[concat(parameters('dataDiskName'),'-1')]",
|
||||
"vhd": {
|
||||
"uri": "[concat(parameters('storageAccountBlobEndpoint'),variables('vmStorageAccountContainerName'),'/',parameters('dataDiskName'),'-1','.vhd')]"
|
||||
"uri": "[concat(parameters('storageAccountBlobEndpoint'),variables('vmStorageAccountContainerName'),parameters('dataDiskName'), '-1','.vhd')]"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
+1
-1
@@ -126,10 +126,10 @@
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"disablePasswordAuthentication": true,
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
|
||||
+1
-1
@@ -127,10 +127,10 @@
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"linuxConfiguration": {
|
||||
"disablePasswordAuthentication": true,
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
|
||||
@@ -108,10 +108,7 @@ func TestVirtualMachineDeployment03(t *testing.T) {
|
||||
m["image_version"] = "ImageVersion"
|
||||
|
||||
var c Config
|
||||
_, err := c.Prepare(m, getPackerConfiguration(), getPackerSSHPasswordCommunicatorConfiguration())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c.Prepare(m, getPackerConfiguration())
|
||||
deployment, err := GetVirtualMachineDeployment(&c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -171,7 +168,7 @@ func TestVirtualMachineDeployment05(t *testing.T) {
|
||||
}
|
||||
|
||||
var c Config
|
||||
_, err := c.Prepare(config, getPackerConfiguration(), getPackerSSHPasswordCommunicatorConfiguration())
|
||||
_, err := c.Prepare(config, getPackerConfiguration())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -238,7 +235,7 @@ func TestVirtualMachineDeployment07(t *testing.T) {
|
||||
}
|
||||
|
||||
var c Config
|
||||
_, err := c.Prepare(config, getPackerConfiguration(), getPackerSSHPasswordCommunicatorConfiguration())
|
||||
_, err := c.Prepare(config, getPackerConfiguration())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -315,7 +312,7 @@ func TestVirtualMachineDeployment09(t *testing.T) {
|
||||
}
|
||||
|
||||
var c Config
|
||||
_, err := c.Prepare(config, getPackerConfiguration(), getPackerSSHPasswordCommunicatorConfiguration())
|
||||
_, err := c.Prepare(config, getPackerConfiguration())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -390,7 +387,7 @@ func TestVirtualMachineDeployment11(t *testing.T) {
|
||||
}
|
||||
|
||||
var c Config
|
||||
_, err := c.Prepare(config, getPackerConfiguration(), getPackerSSHPasswordCommunicatorConfiguration())
|
||||
_, err := c.Prepare(config, getPackerConfiguration())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ type TempName struct {
|
||||
KeyVaultName string
|
||||
ResourceGroupName string
|
||||
OSDiskName string
|
||||
DataDiskName string
|
||||
DataDiskname string
|
||||
NicName string
|
||||
SubnetName string
|
||||
PublicIPAddressName string
|
||||
@@ -36,7 +36,6 @@ func NewTempName(p string) *TempName {
|
||||
tempName.DeploymentName = fmt.Sprintf("%sdp%s", p, suffix)
|
||||
tempName.KeyVaultName = fmt.Sprintf("%skv%s", p, suffix)
|
||||
tempName.OSDiskName = fmt.Sprintf("%sos%s", p, suffix)
|
||||
tempName.DataDiskName = fmt.Sprintf("%sdd%s", p, suffix)
|
||||
tempName.NicName = fmt.Sprintf("%sni%s", p, suffix)
|
||||
tempName.PublicIPAddressName = fmt.Sprintf("%sip%s", p, suffix)
|
||||
tempName.SubnetName = fmt.Sprintf("%ssn%s", p, suffix)
|
||||
|
||||
+37
-121
@@ -24,10 +24,10 @@ import (
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
)
|
||||
|
||||
// BuilderID is the unique ID for this builder
|
||||
@@ -42,10 +42,7 @@ type Config struct {
|
||||
|
||||
// When set to `true`, starts with an empty, unpartitioned disk. Defaults to `false`.
|
||||
FromScratch bool `mapstructure:"from_scratch"`
|
||||
// One of the following can be used as a source for an image:
|
||||
// - a shared image version resource ID
|
||||
// - a managed disk resource ID
|
||||
// - a publisher:offer:sku:version specifier for plaform image sources.
|
||||
// Either a managed disk resource ID or a publisher:offer:sku:version specifier for plaform image sources.
|
||||
Source string `mapstructure:"source" required:"true"`
|
||||
sourceType sourceType
|
||||
|
||||
@@ -88,30 +85,16 @@ 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"`
|
||||
|
||||
// The [storage SKU](https://docs.microsoft.com/en-us/rest/api/compute/disks/createorupdate#diskstorageaccounttypes)
|
||||
// to use for datadisks. Defaults to `Standard_LRS`.
|
||||
DataDiskStorageAccountType string `mapstructure:"data_disk_storage_account_type"`
|
||||
// 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`
|
||||
DataDiskCacheType string `mapstructure:"data_disk_cache_type"`
|
||||
|
||||
// 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 OS disk that will be created. Will be generated if not set.
|
||||
// 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 OS disk snapshot that will be created. Will be generated if not set.
|
||||
// The id of the temporary snapshot that will be created. Will be generated if not set.
|
||||
TemporaryOSDiskSnapshotID string `mapstructure:"temporary_os_disk_snapshot_id"`
|
||||
|
||||
// The prefix for the resource ids of the temporary data disks that will be created. The disks will be suffixed with a number. Will be generated if not set.
|
||||
TemporaryDataDiskIDPrefix string `mapstructure:"temporary_data_disk_id_prefix"`
|
||||
|
||||
// The prefix for the resource ids of the temporary data disk snapshots that will be created. The snapshots will be suffixed with a number. Will be generated if not set.
|
||||
TemporaryDataDiskSnapshotIDPrefix string `mapstructure:"temporary_data_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"`
|
||||
|
||||
@@ -129,7 +112,6 @@ type sourceType string
|
||||
const (
|
||||
sourcePlatformImage sourceType = "PlatformImage"
|
||||
sourceDisk sourceType = "Disk"
|
||||
sourceSharedImage sourceType = "SharedImage"
|
||||
)
|
||||
|
||||
// GetContext implements ContextProvider to allow steps to use the config context
|
||||
@@ -233,26 +215,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if b.config.TemporaryDataDiskIDPrefix == "" {
|
||||
if def, err := interpolate.Render(
|
||||
"/subscriptions/{{ vm `subscription_id` }}/resourceGroups/{{ vm `resource_group` }}/providers/Microsoft.Compute/disks/PackerTemp-datadisk-{{timestamp}}-",
|
||||
&b.config.ctx); err == nil {
|
||||
b.config.TemporaryDataDiskIDPrefix = def
|
||||
} else {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("unable to render temporary data disk id prefix: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
if b.config.TemporaryDataDiskSnapshotIDPrefix == "" {
|
||||
if def, err := interpolate.Render(
|
||||
"/subscriptions/{{ vm `subscription_id` }}/resourceGroups/{{ vm `resource_group` }}/providers/Microsoft.Compute/snapshots/PackerTemp-datadisk-snapshot-{{timestamp}}-",
|
||||
&b.config.ctx); err == nil {
|
||||
b.config.TemporaryDataDiskSnapshotIDPrefix = def
|
||||
} else {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("unable to render temporary data disk snapshot id prefix: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
if b.config.OSDiskStorageAccountType == "" {
|
||||
b.config.OSDiskStorageAccountType = string(compute.PremiumLRS)
|
||||
}
|
||||
@@ -261,14 +223,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
b.config.OSDiskCacheType = string(compute.CachingTypesReadOnly)
|
||||
}
|
||||
|
||||
if b.config.DataDiskStorageAccountType == "" {
|
||||
b.config.DataDiskStorageAccountType = string(compute.PremiumLRS)
|
||||
}
|
||||
|
||||
if b.config.DataDiskCacheType == "" {
|
||||
b.config.DataDiskCacheType = string(compute.CachingTypesReadOnly)
|
||||
}
|
||||
|
||||
if b.config.ImageHyperVGeneration == "" {
|
||||
b.config.ImageHyperVGeneration = string(compute.V1)
|
||||
}
|
||||
@@ -292,16 +246,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
if _, err := client.ParsePlatformImageURN(b.config.Source); err == nil {
|
||||
log.Println("Source is platform image:", b.config.Source)
|
||||
b.config.sourceType = sourcePlatformImage
|
||||
} else if id, err := client.ParseResourceID(b.config.Source); err == nil &&
|
||||
strings.EqualFold(id.Provider, "Microsoft.Compute") &&
|
||||
strings.EqualFold(id.ResourceType.String(), "disks") {
|
||||
} else if id, err := azure.ParseResourceID(b.config.Source); err == nil &&
|
||||
strings.EqualFold(id.Provider, "Microsoft.Compute") && strings.EqualFold(id.ResourceType, "disks") {
|
||||
log.Println("Source is a disk resource ID:", b.config.Source)
|
||||
b.config.sourceType = sourceDisk
|
||||
} else if id, err := client.ParseResourceID(b.config.Source); err == nil &&
|
||||
strings.EqualFold(id.Provider, "Microsoft.Compute") &&
|
||||
strings.EqualFold(id.ResourceType.String(), "galleries/images/versions") {
|
||||
log.Println("Source is a shared image ID:", b.config.Source)
|
||||
b.config.sourceType = sourceSharedImage
|
||||
} else {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, fmt.Errorf("source: %q is not a valid platform image specifier, nor is it a disk resource ID", b.config.Source))
|
||||
@@ -316,14 +264,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("os_disk_storage_account_type: %v", err))
|
||||
}
|
||||
|
||||
if err := checkDiskCacheType(b.config.DataDiskCacheType); err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("data_disk_cache_type: %v", err))
|
||||
}
|
||||
|
||||
if err := checkStorageAccountType(b.config.DataDiskStorageAccountType); err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("data_disk_storage_account_type: %v", err))
|
||||
}
|
||||
|
||||
if b.config.ImageResourceID != "" {
|
||||
r, err := azure.ParseResourceID(b.config.ImageResourceID)
|
||||
if err != nil ||
|
||||
@@ -456,15 +396,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
artifact.Resources = append(artifact.Resources, b.config.SharedImageGalleryDestination.ResourceID(info.SubscriptionID))
|
||||
}
|
||||
if b.config.SkipCleanup {
|
||||
if d, ok := state.GetOk(stateBagKey_Diskset); ok {
|
||||
for _, disk := range d.(Diskset) {
|
||||
artifact.Resources = append(artifact.Resources, disk.String())
|
||||
}
|
||||
if d, ok := state.GetOk(stateBagKey_OSDiskResourceID); ok {
|
||||
artifact.Resources = append(artifact.Resources, d.(string))
|
||||
}
|
||||
if d, ok := state.GetOk(stateBagKey_Snapshotset); ok {
|
||||
for _, snapshot := range d.(Diskset) {
|
||||
artifact.Resources = append(artifact.Resources, snapshot.String())
|
||||
}
|
||||
if d, ok := state.GetOk(stateBagKey_OSDiskSnapshotResourceID); ok {
|
||||
artifact.Resources = append(artifact.Resources, d.(string))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,7 +410,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
func buildsteps(config Config, info *client.ComputeInfo) []multistep.Step {
|
||||
// Build the steps
|
||||
var steps []multistep.Step
|
||||
addSteps := func(s ...multistep.Step) { // convenience function
|
||||
addSteps := func(s ...multistep.Step) { // convenience
|
||||
steps = append(steps, s...)
|
||||
}
|
||||
|
||||
@@ -492,12 +428,12 @@ func buildsteps(config Config, info *client.ComputeInfo) []multistep.Step {
|
||||
}
|
||||
|
||||
if config.FromScratch {
|
||||
addSteps(&StepCreateNewDiskset{
|
||||
OSDiskID: config.TemporaryOSDiskID,
|
||||
OSDiskSizeGB: config.OSDiskSizeGB,
|
||||
OSDiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: config.ImageHyperVGeneration,
|
||||
Location: info.Location})
|
||||
addSteps(&StepCreateNewDisk{
|
||||
ResourceID: config.TemporaryOSDiskID,
|
||||
DiskSizeGB: config.OSDiskSizeGB,
|
||||
DiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: config.ImageHyperVGeneration,
|
||||
Location: info.Location})
|
||||
} else {
|
||||
switch config.sourceType {
|
||||
case sourcePlatformImage:
|
||||
@@ -510,13 +446,13 @@ func buildsteps(config Config, info *client.ComputeInfo) []multistep.Step {
|
||||
})
|
||||
}
|
||||
addSteps(
|
||||
&StepCreateNewDiskset{
|
||||
OSDiskID: config.TemporaryOSDiskID,
|
||||
OSDiskSizeGB: config.OSDiskSizeGB,
|
||||
OSDiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: config.ImageHyperVGeneration,
|
||||
Location: info.Location,
|
||||
SourcePlatformImage: pi,
|
||||
&StepCreateNewDisk{
|
||||
ResourceID: config.TemporaryOSDiskID,
|
||||
DiskSizeGB: config.OSDiskSizeGB,
|
||||
DiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: config.ImageHyperVGeneration,
|
||||
Location: info.Location,
|
||||
PlatformImage: pi,
|
||||
|
||||
SkipCleanup: config.SkipCleanup,
|
||||
})
|
||||
@@ -530,32 +466,13 @@ func buildsteps(config Config, info *client.ComputeInfo) []multistep.Step {
|
||||
SourceDiskResourceID: config.Source,
|
||||
Location: info.Location,
|
||||
},
|
||||
&StepCreateNewDiskset{
|
||||
OSDiskID: config.TemporaryOSDiskID,
|
||||
OSDiskSizeGB: config.OSDiskSizeGB,
|
||||
OSDiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
HyperVGeneration: config.ImageHyperVGeneration,
|
||||
SourceOSDiskResourceID: config.Source,
|
||||
Location: info.Location,
|
||||
|
||||
SkipCleanup: config.SkipCleanup,
|
||||
})
|
||||
|
||||
case sourceSharedImage:
|
||||
addSteps(
|
||||
&StepVerifySharedImageSource{
|
||||
SharedImageID: config.Source,
|
||||
SubscriptionID: info.SubscriptionID,
|
||||
Location: info.Location,
|
||||
},
|
||||
&StepCreateNewDiskset{
|
||||
OSDiskID: config.TemporaryOSDiskID,
|
||||
DataDiskIDPrefix: config.TemporaryDataDiskIDPrefix,
|
||||
OSDiskSizeGB: config.OSDiskSizeGB,
|
||||
OSDiskStorageAccountType: config.OSDiskStorageAccountType,
|
||||
DataDiskStorageAccountType: config.DataDiskStorageAccountType,
|
||||
SourceImageResourceID: 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,
|
||||
})
|
||||
@@ -599,11 +516,10 @@ func buildsteps(config Config, info *client.ComputeInfo) []multistep.Step {
|
||||
}
|
||||
if hasValidSharedImage {
|
||||
addSteps(
|
||||
&StepCreateSnapshotset{
|
||||
OSDiskSnapshotID: config.TemporaryOSDiskSnapshotID,
|
||||
DataDiskSnapshotIDPrefix: config.TemporaryDataDiskSnapshotIDPrefix,
|
||||
Location: info.Location,
|
||||
SkipCleanup: config.SkipCleanup,
|
||||
&StepCreateSnapshot{
|
||||
ResourceID: config.TemporaryOSDiskSnapshotID,
|
||||
Location: info.Location,
|
||||
SkipCleanup: config.SkipCleanup,
|
||||
},
|
||||
&StepCreateSharedImageVersion{
|
||||
Destination: config.SharedImageGalleryDestination,
|
||||
|
||||
@@ -9,44 +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" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
CloudEnvironmentName *string `mapstructure:"cloud_environment_name" required:"false" cty:"cloud_environment_name" hcl:"cloud_environment_name"`
|
||||
ClientID *string `mapstructure:"client_id" cty:"client_id" hcl:"client_id"`
|
||||
ClientSecret *string `mapstructure:"client_secret" cty:"client_secret" hcl:"client_secret"`
|
||||
ClientCertPath *string `mapstructure:"client_cert_path" cty:"client_cert_path" hcl:"client_cert_path"`
|
||||
ClientJWT *string `mapstructure:"client_jwt" cty:"client_jwt" hcl:"client_jwt"`
|
||||
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
|
||||
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
|
||||
SubscriptionID *string `mapstructure:"subscription_id" cty:"subscription_id" hcl:"subscription_id"`
|
||||
FromScratch *bool `mapstructure:"from_scratch" cty:"from_scratch" hcl:"from_scratch"`
|
||||
Source *string `mapstructure:"source" required:"true" cty:"source" hcl:"source"`
|
||||
CommandWrapper *string `mapstructure:"command_wrapper" cty:"command_wrapper" hcl:"command_wrapper"`
|
||||
PreMountCommands []string `mapstructure:"pre_mount_commands" cty:"pre_mount_commands" hcl:"pre_mount_commands"`
|
||||
MountOptions []string `mapstructure:"mount_options" cty:"mount_options" hcl:"mount_options"`
|
||||
MountPartition *string `mapstructure:"mount_partition" cty:"mount_partition" hcl:"mount_partition"`
|
||||
MountPath *string `mapstructure:"mount_path" cty:"mount_path" hcl:"mount_path"`
|
||||
PostMountCommands []string `mapstructure:"post_mount_commands" cty:"post_mount_commands" hcl:"post_mount_commands"`
|
||||
ChrootMounts [][]string `mapstructure:"chroot_mounts" cty:"chroot_mounts" hcl:"chroot_mounts"`
|
||||
CopyFiles []string `mapstructure:"copy_files" cty:"copy_files" hcl:"copy_files"`
|
||||
OSDiskSizeGB *int32 `mapstructure:"os_disk_size_gb" cty:"os_disk_size_gb" hcl:"os_disk_size_gb"`
|
||||
OSDiskStorageAccountType *string `mapstructure:"os_disk_storage_account_type" cty:"os_disk_storage_account_type" hcl:"os_disk_storage_account_type"`
|
||||
OSDiskCacheType *string `mapstructure:"os_disk_cache_type" cty:"os_disk_cache_type" hcl:"os_disk_cache_type"`
|
||||
DataDiskStorageAccountType *string `mapstructure:"data_disk_storage_account_type" cty:"data_disk_storage_account_type" hcl:"data_disk_storage_account_type"`
|
||||
DataDiskCacheType *string `mapstructure:"data_disk_cache_type" cty:"data_disk_cache_type" hcl:"data_disk_cache_type"`
|
||||
ImageHyperVGeneration *string `mapstructure:"image_hyperv_generation" cty:"image_hyperv_generation" hcl:"image_hyperv_generation"`
|
||||
TemporaryOSDiskID *string `mapstructure:"temporary_os_disk_id" cty:"temporary_os_disk_id" hcl:"temporary_os_disk_id"`
|
||||
TemporaryOSDiskSnapshotID *string `mapstructure:"temporary_os_disk_snapshot_id" cty:"temporary_os_disk_snapshot_id" hcl:"temporary_os_disk_snapshot_id"`
|
||||
TemporaryDataDiskIDPrefix *string `mapstructure:"temporary_data_disk_id_prefix" cty:"temporary_data_disk_id_prefix" hcl:"temporary_data_disk_id_prefix"`
|
||||
TemporaryDataDiskSnapshotIDPrefix *string `mapstructure:"temporary_data_disk_snapshot_id" cty:"temporary_data_disk_snapshot_id" hcl:"temporary_data_disk_snapshot_id"`
|
||||
SkipCleanup *bool `mapstructure:"skip_cleanup" cty:"skip_cleanup" hcl:"skip_cleanup"`
|
||||
ImageResourceID *string `mapstructure:"image_resource_id" cty:"image_resource_id" hcl:"image_resource_id"`
|
||||
SharedImageGalleryDestination *FlatSharedImageGalleryDestination `mapstructure:"shared_image_destination" cty:"shared_image_destination" hcl:"shared_image_destination"`
|
||||
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.
|
||||
@@ -61,44 +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.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},
|
||||
"data_disk_storage_account_type": &hcldec.AttrSpec{Name: "data_disk_storage_account_type", Type: cty.String, Required: false},
|
||||
"data_disk_cache_type": &hcldec.AttrSpec{Name: "data_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},
|
||||
"temporary_data_disk_id_prefix": &hcldec.AttrSpec{Name: "temporary_data_disk_id_prefix", Type: cty.String, Required: false},
|
||||
"temporary_data_disk_snapshot_id": &hcldec.AttrSpec{Name: "temporary_data_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())},
|
||||
"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
|
||||
}
|
||||
|
||||
@@ -4,10 +4,9 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
)
|
||||
|
||||
func TestBuilder_Prepare(t *testing.T) {
|
||||
@@ -28,12 +27,6 @@ func TestBuilder_Prepare(t *testing.T) {
|
||||
"subscription_id": "789",
|
||||
"source": "credativ:Debian:9:latest",
|
||||
"image_resource_id": "/subscriptions/789/resourceGroups/otherrgname/providers/Microsoft.Compute/images/MyDebianOSImage-{{timestamp}}",
|
||||
"shared_image_destination": config{
|
||||
"resource_group": "otherrgname",
|
||||
"gallery_name": "myGallery",
|
||||
"image_name": "imageName",
|
||||
"image_version": "1.0.2",
|
||||
},
|
||||
},
|
||||
validate: func(c Config) {
|
||||
if c.OSDiskSizeGB != 0 {
|
||||
@@ -92,19 +85,6 @@ func TestBuilder_Prepare(t *testing.T) {
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "from shared image",
|
||||
config: config{
|
||||
"shared_image_destination": config{
|
||||
"resource_group": "otherrgname",
|
||||
"gallery_name": "myGallery",
|
||||
"image_name": "imageName",
|
||||
"image_version": "1.0.2",
|
||||
},
|
||||
"source": "/subscriptions/789/resourceGroups/testrg/providers/Microsoft.Compute/disks/diskname",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "err: no output",
|
||||
config: config{
|
||||
@@ -151,9 +131,9 @@ func Test_buildsteps(t *testing.T) {
|
||||
config: Config{FromScratch: true},
|
||||
verify: func(steps []multistep.Step, _ *testing.T) {
|
||||
for _, s := range steps {
|
||||
if s, ok := s.(*StepCreateNewDiskset); ok {
|
||||
if s.SourceOSDiskResourceID == "" &&
|
||||
s.SourcePlatformImage == nil {
|
||||
if s, ok := s.(*StepCreateNewDisk); ok {
|
||||
if s.SourceDiskResourceID == "" &&
|
||||
s.PlatformImage == nil {
|
||||
return
|
||||
}
|
||||
t.Errorf("found misconfigured StepCreateNewDisk: %+v", s)
|
||||
@@ -166,10 +146,10 @@ func Test_buildsteps(t *testing.T) {
|
||||
config: Config{Source: "publisher:offer:sku:version", sourceType: sourcePlatformImage},
|
||||
verify: func(steps []multistep.Step, _ *testing.T) {
|
||||
for _, s := range steps {
|
||||
if s, ok := s.(*StepCreateNewDiskset); ok {
|
||||
if s.SourceOSDiskResourceID == "" &&
|
||||
s.SourcePlatformImage != nil &&
|
||||
s.SourcePlatformImage.Publisher == "publisher" {
|
||||
if s, ok := s.(*StepCreateNewDisk); ok {
|
||||
if s.SourceDiskResourceID == "" &&
|
||||
s.PlatformImage != nil &&
|
||||
s.PlatformImage.Publisher == "publisher" {
|
||||
return
|
||||
}
|
||||
t.Errorf("found misconfigured StepCreateNewDisk: %+v", s)
|
||||
@@ -197,9 +177,9 @@ func Test_buildsteps(t *testing.T) {
|
||||
config: Config{Source: "diskresourceid", sourceType: sourceDisk},
|
||||
verify: func(steps []multistep.Step, _ *testing.T) {
|
||||
for _, s := range steps {
|
||||
if s, ok := s.(*StepCreateNewDiskset); ok {
|
||||
if s.SourceOSDiskResourceID == "diskresourceid" &&
|
||||
s.SourcePlatformImage == nil {
|
||||
if s, ok := s.(*StepCreateNewDisk); ok {
|
||||
if s.SourceDiskResourceID == "diskresourceid" &&
|
||||
s.PlatformImage == nil {
|
||||
return
|
||||
}
|
||||
t.Errorf("found misconfigured StepCreateNewDisk: %+v", s)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package chroot
|
||||
|
||||
const (
|
||||
stateBagKey_Diskset = "diskset"
|
||||
stateBagKey_Snapshotset = "snapshotset"
|
||||
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/services/compute/mgmt/2019-12-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"
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-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"
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package chroot
|
||||
|
||||
import "github.com/hashicorp/packer/builder/azure/common/client"
|
||||
|
||||
// Diskset represents all of the disks or snapshots associated with an image.
|
||||
// It maps lun to resource ids. The OS disk is stored with lun=-1.
|
||||
type Diskset map[int32]client.Resource
|
||||
|
||||
// OS return the OS disk resource ID or nil if it is not assigned
|
||||
func (ds Diskset) OS() *client.Resource {
|
||||
if r, ok := ds[-1]; ok {
|
||||
return &r
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Data return the data disk resource ID or nil if it is not assigned
|
||||
func (ds Diskset) Data(lun int32) *client.Resource {
|
||||
if r, ok := ds[lun]; ok {
|
||||
return &r
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package chroot
|
||||
|
||||
import "github.com/hashicorp/packer/builder/azure/common/client"
|
||||
|
||||
// diskset easily creates a diskset for testing
|
||||
func diskset(ids ...string) Diskset {
|
||||
diskset := make(Diskset)
|
||||
for i, id := range ids {
|
||||
r, err := client.ParseResourceID(id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
diskset[int32(i-1)] = r
|
||||
}
|
||||
return diskset
|
||||
}
|
||||
@@ -9,12 +9,12 @@ import (
|
||||
// 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" hcl:"resource_group"`
|
||||
GalleryName *string `mapstructure:"gallery_name" required:"true" cty:"gallery_name" hcl:"gallery_name"`
|
||||
ImageName *string `mapstructure:"image_name" required:"true" cty:"image_name" hcl:"image_name"`
|
||||
ImageVersion *string `mapstructure:"image_version" required:"true" cty:"image_version" hcl:"image_version"`
|
||||
TargetRegions []FlatTargetRegion `mapstructure:"target_regions" cty:"target_regions" hcl:"target_regions"`
|
||||
ExcludeFromLatest *bool `mapstructure:"exlude_from_latest" cty:"exlude_from_latest" hcl:"exlude_from_latest"`
|
||||
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.
|
||||
@@ -42,9 +42,9 @@ func (*FlatSharedImageGalleryDestination) HCL2Spec() map[string]hcldec.Spec {
|
||||
// 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" hcl:"name"`
|
||||
ReplicaCount *int32 `mapstructure:"replicas" cty:"replicas" hcl:"replicas"`
|
||||
StorageAccountType *string `mapstructure:"storage_account_type" cty:"storage_account_type" hcl:"storage_account_type"`
|
||||
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.
|
||||
|
||||
@@ -20,8 +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)
|
||||
diskset := state.Get(stateBagKey_Diskset).(Diskset)
|
||||
diskResourceID := diskset.OS().String()
|
||||
diskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
|
||||
ui.Say(fmt.Sprintf("Attaching disk '%s'", diskResourceID))
|
||||
|
||||
@@ -68,8 +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)
|
||||
diskset := state.Get(stateBagKey_Diskset).(Diskset)
|
||||
diskResourceID := diskset.OS().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/services/compute/mgmt/2019-12-01/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(stateBagKey_Diskset, diskset("/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) {
|
||||
|
||||
@@ -4,9 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-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"
|
||||
@@ -17,26 +16,26 @@ import (
|
||||
var _ multistep.Step = &StepCreateImage{}
|
||||
|
||||
type StepCreateImage struct {
|
||||
ImageResourceID string
|
||||
ImageOSState string
|
||||
OSDiskStorageAccountType string
|
||||
OSDiskCacheType string
|
||||
DataDiskStorageAccountType string
|
||||
DataDiskCacheType string
|
||||
Location string
|
||||
ImageResourceID string
|
||||
ImageOSState string
|
||||
OSDiskStorageAccountType string
|
||||
OSDiskCacheType string
|
||||
Location string
|
||||
|
||||
imageResource azure.Resource
|
||||
}
|
||||
|
||||
func (s *StepCreateImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
diskset := state.Get(stateBagKey_Diskset).(Diskset)
|
||||
diskResourceID := diskset.OS().String()
|
||||
diskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating image %s\n using %s for os disk.",
|
||||
s.ImageResourceID,
|
||||
diskResourceID))
|
||||
|
||||
imageResource, err := azure.ParseResourceID(s.ImageResourceID)
|
||||
var err error
|
||||
s.imageResource, err = azure.ParseResourceID(s.ImageResourceID)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("StepCreateImage.Run: error: %+v", err)
|
||||
@@ -66,31 +65,10 @@ func (s *StepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul
|
||||
},
|
||||
// Tags: nil,
|
||||
}
|
||||
|
||||
var datadisks []compute.ImageDataDisk
|
||||
for lun, resource := range diskset {
|
||||
if lun != -1 {
|
||||
ui.Say(fmt.Sprintf(" using %q for data disk (lun %d).", resource, lun))
|
||||
|
||||
datadisks = append(datadisks, compute.ImageDataDisk{
|
||||
Lun: to.Int32Ptr(lun),
|
||||
ManagedDisk: &compute.SubResource{ID: to.StringPtr(resource.String())},
|
||||
StorageAccountType: compute.StorageAccountTypes(s.DataDiskStorageAccountType),
|
||||
Caching: compute.CachingTypes(s.DataDiskCacheType),
|
||||
})
|
||||
}
|
||||
}
|
||||
if datadisks != nil {
|
||||
sort.Slice(datadisks, func(i, j int) bool {
|
||||
return *datadisks[i].Lun < *datadisks[j].Lun
|
||||
})
|
||||
image.ImageProperties.StorageProfile.DataDisks = &datadisks
|
||||
}
|
||||
|
||||
f, err := azcli.ImagesClient().CreateOrUpdate(
|
||||
ctx,
|
||||
imageResource.ResourceGroup,
|
||||
imageResource.ResourceName,
|
||||
s.imageResource.ResourceGroup,
|
||||
s.imageResource.ResourceName,
|
||||
image)
|
||||
if err == nil {
|
||||
log.Println("Image creation in process...")
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
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-12-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
func TestStepCreateImage_Run(t *testing.T) {
|
||||
type fields struct {
|
||||
ImageResourceID string
|
||||
ImageOSState string
|
||||
OSDiskStorageAccountType string
|
||||
OSDiskCacheType string
|
||||
DataDiskStorageAccountType string
|
||||
DataDiskCacheType string
|
||||
Location string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
diskset Diskset
|
||||
want multistep.StepAction
|
||||
wantPutBody string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
fields: fields{
|
||||
ImageResourceID: "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/images/myImage",
|
||||
Location: "location1",
|
||||
OSDiskStorageAccountType: "Standard_LRS",
|
||||
OSDiskCacheType: "ReadWrite",
|
||||
DataDiskStorageAccountType: "Premium_LRS",
|
||||
DataDiskCacheType: "ReadOnly",
|
||||
},
|
||||
diskset: diskset(
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/osdisk",
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/datadisk0",
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/datadisk1",
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/datadisk2"),
|
||||
want: multistep.ActionContinue,
|
||||
wantPutBody: `{
|
||||
"location": "location1",
|
||||
"properties": {
|
||||
"storageProfile": {
|
||||
"osDisk": {
|
||||
"osType": "Linux",
|
||||
"managedDisk": {
|
||||
"id": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/osdisk"
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
"storageAccountType": "Standard_LRS"
|
||||
},
|
||||
"dataDisks": [
|
||||
{
|
||||
"lun": 0,
|
||||
"managedDisk": {
|
||||
"id": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/datadisk0"
|
||||
},
|
||||
"caching": "ReadOnly",
|
||||
"storageAccountType": "Premium_LRS"
|
||||
},
|
||||
{
|
||||
"lun": 1,
|
||||
"managedDisk": {
|
||||
"id": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/datadisk1"
|
||||
},
|
||||
"caching": "ReadOnly",
|
||||
"storageAccountType": "Premium_LRS"
|
||||
},
|
||||
{
|
||||
"lun": 2,
|
||||
"managedDisk": {
|
||||
"id": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/datadisk2"
|
||||
},
|
||||
"caching": "ReadOnly",
|
||||
"storageAccountType": "Premium_LRS"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
ic := compute.NewImagesClient("subscriptionID")
|
||||
ic.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if r.Method != "PUT" {
|
||||
t.Fatal("Expected only a PUT call")
|
||||
}
|
||||
if tt.wantPutBody != "" {
|
||||
b, _ := ioutil.ReadAll(r.Body)
|
||||
expectedPutBody := regexp.MustCompile(`[\s\n]`).ReplaceAllString(tt.wantPutBody, "")
|
||||
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{
|
||||
ImagesClientMock: ic,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
state.Put(stateBagKey_Diskset, tt.diskset)
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StepCreateImage{
|
||||
ImageResourceID: tt.fields.ImageResourceID,
|
||||
ImageOSState: tt.fields.ImageOSState,
|
||||
OSDiskStorageAccountType: tt.fields.OSDiskStorageAccountType,
|
||||
OSDiskCacheType: tt.fields.OSDiskCacheType,
|
||||
DataDiskStorageAccountType: tt.fields.DataDiskStorageAccountType,
|
||||
DataDiskCacheType: tt.fields.DataDiskCacheType,
|
||||
Location: tt.fields.Location,
|
||||
}
|
||||
if got := s.Run(context.TODO(), state); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("StepCreateImage.Run() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
var _ multistep.Step = &StepCreateNewDisk{}
|
||||
|
||||
type StepCreateNewDisk struct {
|
||||
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
|
||||
|
||||
SourceDiskResourceID string
|
||||
|
||||
SkipCleanup bool
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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),
|
||||
Sku: &compute.DiskSku{
|
||||
Name: compute.DiskStorageAccountTypes(s.DiskStorageAccountType),
|
||||
},
|
||||
//Zones: nil,
|
||||
DiskProperties: &compute.DiskProperties{
|
||||
OsType: "Linux",
|
||||
HyperVGeneration: compute.HyperVGeneration(s.HyperVGeneration),
|
||||
CreationData: &compute.CreationData{},
|
||||
},
|
||||
//Tags: map[string]*string{
|
||||
}
|
||||
|
||||
if s.DiskSizeGB > 0 {
|
||||
disk.DiskProperties.DiskSizeGB = to.Int32Ptr(s.DiskSizeGB)
|
||||
}
|
||||
|
||||
if s.SourceDiskResourceID != "" {
|
||||
disk.CreationData.CreateOption = compute.Copy
|
||||
disk.CreationData.SourceResourceID = to.StringPtr(s.SourceDiskResourceID)
|
||||
} else if s.PlatformImage == nil {
|
||||
disk.CreationData.CreateOption = compute.Empty
|
||||
} else {
|
||||
disk.CreationData.CreateOption = compute.FromImage
|
||||
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)),
|
||||
}
|
||||
}
|
||||
|
||||
f, err := azcli.DisksClient().CreateOrUpdate(ctx, s.resourceGroup, s.diskName, disk)
|
||||
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("StepCreateNewDisk.Run: error: %+v", err)
|
||||
err := fmt.Errorf(
|
||||
"error creating new disk '%s': %v", s.ResourceID, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCreateNewDisk) Cleanup(state multistep.StateBag) {
|
||||
if !s.SkipCleanup {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
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", s.ResourceID, err))
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Deleting disk %q", s.ResourceID))
|
||||
|
||||
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 disk '%s': %v.", s.ResourceID, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
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 TestStepCreateNewDisk_Run(t *testing.T) {
|
||||
type fields struct {
|
||||
ResourceID string
|
||||
DiskSizeGB int32
|
||||
DiskStorageAccountType string
|
||||
HyperVGeneration string
|
||||
Location string
|
||||
PlatformImage *client.PlatformImage
|
||||
SourceDiskResourceID string
|
||||
|
||||
expectedPutDiskBody string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want multistep.StepAction
|
||||
}{
|
||||
{
|
||||
name: "from disk",
|
||||
fields: fields{
|
||||
ResourceID: "/subscriptions/SubscriptionID/resourcegroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName",
|
||||
DiskSizeGB: 42,
|
||||
DiskStorageAccountType: string(compute.PremiumLRS),
|
||||
HyperVGeneration: string(compute.V1),
|
||||
Location: "westus",
|
||||
SourceDiskResourceID: "SourceDisk",
|
||||
|
||||
expectedPutDiskBody: `
|
||||
{
|
||||
"location": "westus",
|
||||
"properties": {
|
||||
"osType": "Linux",
|
||||
"hyperVGeneration": "V1",
|
||||
"creationData": {
|
||||
"createOption": "Copy",
|
||||
"sourceResourceId": "SourceDisk"
|
||||
},
|
||||
"diskSizeGB": 42
|
||||
},
|
||||
"sku": {
|
||||
"name": "Premium_LRS"
|
||||
}
|
||||
}`,
|
||||
},
|
||||
want: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "from image",
|
||||
fields: fields{
|
||||
ResourceID: "/subscriptions/SubscriptionID/resourcegroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName",
|
||||
DiskStorageAccountType: string(compute.StandardLRS),
|
||||
HyperVGeneration: string(compute.V1),
|
||||
Location: "westus",
|
||||
PlatformImage: &client.PlatformImage{
|
||||
Publisher: "Microsoft",
|
||||
Offer: "Windows",
|
||||
Sku: "2016-DataCenter",
|
||||
Version: "2016.1.4",
|
||||
},
|
||||
|
||||
expectedPutDiskBody: `
|
||||
{
|
||||
"location": "westus",
|
||||
"properties": {
|
||||
"osType": "Linux",
|
||||
"hyperVGeneration": "V1",
|
||||
"creationData": {
|
||||
"createOption":"FromImage",
|
||||
"imageReference": {
|
||||
"id":"/subscriptions/SubscriptionID/providers/Microsoft.Compute/locations/westus/publishers/Microsoft/artifacttypes/vmimage/offers/Windows/skus/2016-DataCenter/versions/2016.1.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sku": {
|
||||
"name": "Standard_LRS"
|
||||
}
|
||||
}`,
|
||||
},
|
||||
want: multistep.ActionContinue,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := StepCreateNewDisk{
|
||||
ResourceID: tt.fields.ResourceID,
|
||||
DiskSizeGB: tt.fields.DiskSizeGB,
|
||||
DiskStorageAccountType: tt.fields.DiskStorageAccountType,
|
||||
HyperVGeneration: tt.fields.HyperVGeneration,
|
||||
Location: tt.fields.Location,
|
||||
PlatformImage: tt.fields.PlatformImage,
|
||||
SourceDiskResourceID: tt.fields.SourceDiskResourceID,
|
||||
}
|
||||
|
||||
expectedPutDiskBody := regexp.MustCompile(`[\s\n]`).ReplaceAllString(tt.fields.expectedPutDiskBody, "")
|
||||
|
||||
m := compute.NewDisksClient("subscriptionId")
|
||||
m.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if r.Method != "PUT" {
|
||||
t.Fatal("Expected only a PUT disk call")
|
||||
}
|
||||
b, _ := ioutil.ReadAll(r.Body)
|
||||
if string(b) != expectedPutDiskBody {
|
||||
t.Fatalf("expected body to be %q, but got %q", expectedPutDiskBody, string(b))
|
||||
}
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
})
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
DisksClientMock: m,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
|
||||
if got := s.Run(context.TODO(), state); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("StepCreateNewDisk.Run() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
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-12-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
)
|
||||
|
||||
var _ multistep.Step = &StepCreateNewDiskset{}
|
||||
|
||||
type StepCreateNewDiskset struct {
|
||||
OSDiskID string // Disk ID
|
||||
OSDiskSizeGB int32 // optional, ignored if 0
|
||||
OSDiskStorageAccountType string // from compute.DiskStorageAccountTypes
|
||||
DataDiskStorageAccountType string // from compute.DiskStorageAccountTypes
|
||||
|
||||
DataDiskIDPrefix string
|
||||
|
||||
disks Diskset
|
||||
|
||||
HyperVGeneration string // For OS disk
|
||||
|
||||
// Copy another disk
|
||||
SourceOSDiskResourceID string
|
||||
|
||||
// Extract from platform image
|
||||
SourcePlatformImage *client.PlatformImage
|
||||
// Extract from shared image
|
||||
SourceImageResourceID string
|
||||
// Location is needed for platform and shared images
|
||||
Location string
|
||||
|
||||
SkipCleanup bool
|
||||
}
|
||||
|
||||
func (s *StepCreateNewDiskset) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
s.disks = make(Diskset)
|
||||
|
||||
errorMessage := func(format string, params ...interface{}) multistep.StepAction {
|
||||
err := fmt.Errorf("StepCreateNewDiskset.Run: error: "+format, params...)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// we always have an OS disk
|
||||
osDisk, err := client.ParseResourceID(s.OSDiskID)
|
||||
if err != nil {
|
||||
return errorMessage("error parsing resource id '%s': %v", s.OSDiskID, err)
|
||||
}
|
||||
if !strings.EqualFold(osDisk.Provider, "Microsoft.Compute") ||
|
||||
!strings.EqualFold(osDisk.ResourceType.String(), "disks") {
|
||||
return errorMessage("Resource %q is not of type Microsoft.Compute/disks", s.OSDiskID)
|
||||
}
|
||||
|
||||
// transform step config to disk model
|
||||
disk := s.getOSDiskDefinition(azcli.SubscriptionID())
|
||||
|
||||
// Initiate disk creation
|
||||
f, err := azcli.DisksClient().CreateOrUpdate(ctx, osDisk.ResourceGroup, osDisk.ResourceName.String(), disk)
|
||||
if err != nil {
|
||||
return errorMessage("Failed to initiate resource creation: %q", osDisk)
|
||||
}
|
||||
s.disks[-1] = osDisk // save the resoure we just create in our disk set
|
||||
state.Put(stateBagKey_Diskset, s.disks) // update the statebag
|
||||
ui.Say(fmt.Sprintf("Creating disk %q", s.OSDiskID))
|
||||
|
||||
type Future struct {
|
||||
client.Resource
|
||||
compute.DisksCreateOrUpdateFuture
|
||||
}
|
||||
futures := []Future{{osDisk, f}}
|
||||
|
||||
if s.SourceImageResourceID != "" {
|
||||
// retrieve image to see if there are any datadisks
|
||||
imageID, err := client.ParseResourceID(s.SourceImageResourceID)
|
||||
if err != nil {
|
||||
return errorMessage("could not parse source image id %q: %v", s.SourceImageResourceID, err)
|
||||
}
|
||||
if !strings.EqualFold(imageID.Provider+"/"+imageID.ResourceType.String(),
|
||||
"Microsoft.Compute/galleries/images/versions") {
|
||||
return errorMessage("source image id is not a shared image version %q, expected type 'Microsoft.Compute/galleries/images/versions'", imageID)
|
||||
}
|
||||
image, err := azcli.GalleryImageVersionsClient().Get(ctx,
|
||||
imageID.ResourceGroup,
|
||||
imageID.ResourceName[0], imageID.ResourceName[1], imageID.ResourceName[2], "")
|
||||
if err != nil {
|
||||
return errorMessage("error retrieving source image %q: %v", imageID, err)
|
||||
}
|
||||
if image.GalleryImageVersionProperties != nil &&
|
||||
image.GalleryImageVersionProperties.StorageProfile != nil &&
|
||||
image.GalleryImageVersionProperties.StorageProfile.DataDiskImages != nil {
|
||||
for i, ddi := range *image.GalleryImageVersionProperties.StorageProfile.DataDiskImages {
|
||||
if ddi.Lun == nil {
|
||||
return errorMessage("unexpected: lun is null for data disk # %d", i)
|
||||
}
|
||||
datadiskID, err := client.ParseResourceID(fmt.Sprintf("%s%d", s.DataDiskIDPrefix, *ddi.Lun))
|
||||
if err != nil {
|
||||
return errorMessage("unable to construct resource id for datadisk: %v", err)
|
||||
}
|
||||
|
||||
disk := s.getDatadiskDefinitionFromImage(*ddi.Lun)
|
||||
// Initiate disk creation
|
||||
f, err := azcli.DisksClient().CreateOrUpdate(ctx, datadiskID.ResourceGroup, datadiskID.ResourceName.String(), disk)
|
||||
if err != nil {
|
||||
return errorMessage("Failed to initiate resource creation: %q", datadiskID)
|
||||
}
|
||||
s.disks[*ddi.Lun] = datadiskID // save the resoure we just create in our disk set
|
||||
state.Put(stateBagKey_Diskset, s.disks) // update the statebag
|
||||
ui.Say(fmt.Sprintf("Creating disk %q", datadiskID))
|
||||
|
||||
futures = append(futures, Future{datadiskID, f})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui.Say("Waiting for disks to be created.")
|
||||
|
||||
// Wait for completion
|
||||
for _, f := range futures {
|
||||
cli := azcli.PollClient() // quick polling for quick operations
|
||||
cli.PollingDelay = time.Second
|
||||
err = f.WaitForCompletionRef(ctx, cli)
|
||||
if err != nil {
|
||||
return errorMessage(
|
||||
"error creating new disk '%s': %v", f.Resource, err)
|
||||
}
|
||||
ui.Say(fmt.Sprintf("Disk %q created", f.Resource))
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s StepCreateNewDiskset) getOSDiskDefinition(subscriptionID string) compute.Disk {
|
||||
disk := compute.Disk{
|
||||
Location: to.StringPtr(s.Location),
|
||||
DiskProperties: &compute.DiskProperties{
|
||||
OsType: "Linux",
|
||||
CreationData: &compute.CreationData{},
|
||||
},
|
||||
}
|
||||
|
||||
if s.OSDiskStorageAccountType != "" {
|
||||
disk.Sku = &compute.DiskSku{
|
||||
Name: compute.DiskStorageAccountTypes(s.OSDiskStorageAccountType),
|
||||
}
|
||||
}
|
||||
|
||||
if s.HyperVGeneration != "" {
|
||||
disk.DiskProperties.HyperVGeneration = compute.HyperVGeneration(s.HyperVGeneration)
|
||||
}
|
||||
|
||||
if s.OSDiskSizeGB > 0 {
|
||||
disk.DiskProperties.DiskSizeGB = to.Int32Ptr(s.OSDiskSizeGB)
|
||||
}
|
||||
|
||||
switch {
|
||||
case s.SourcePlatformImage != nil:
|
||||
disk.CreationData.CreateOption = compute.FromImage
|
||||
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",
|
||||
subscriptionID, s.Location,
|
||||
s.SourcePlatformImage.Publisher, s.SourcePlatformImage.Offer, s.SourcePlatformImage.Sku, s.SourcePlatformImage.Version)),
|
||||
}
|
||||
case s.SourceOSDiskResourceID != "":
|
||||
disk.CreationData.CreateOption = compute.Copy
|
||||
disk.CreationData.SourceResourceID = to.StringPtr(s.SourceOSDiskResourceID)
|
||||
case s.SourceImageResourceID != "":
|
||||
disk.CreationData.CreateOption = compute.FromImage
|
||||
disk.CreationData.GalleryImageReference = &compute.ImageDiskReference{
|
||||
ID: to.StringPtr(s.SourceImageResourceID),
|
||||
}
|
||||
default:
|
||||
disk.CreationData.CreateOption = compute.Empty
|
||||
}
|
||||
return disk
|
||||
}
|
||||
|
||||
func (s StepCreateNewDiskset) getDatadiskDefinitionFromImage(lun int32) compute.Disk {
|
||||
disk := compute.Disk{
|
||||
Location: to.StringPtr(s.Location),
|
||||
DiskProperties: &compute.DiskProperties{
|
||||
CreationData: &compute.CreationData{},
|
||||
},
|
||||
}
|
||||
|
||||
disk.CreationData.CreateOption = compute.FromImage
|
||||
disk.CreationData.GalleryImageReference = &compute.ImageDiskReference{
|
||||
ID: to.StringPtr(s.SourceImageResourceID),
|
||||
Lun: to.Int32Ptr(lun),
|
||||
}
|
||||
|
||||
if s.DataDiskStorageAccountType != "" {
|
||||
disk.Sku = &compute.DiskSku{
|
||||
Name: compute.DiskStorageAccountTypes(s.DataDiskStorageAccountType),
|
||||
}
|
||||
}
|
||||
return disk
|
||||
}
|
||||
|
||||
func (s *StepCreateNewDiskset) Cleanup(state multistep.StateBag) {
|
||||
if !s.SkipCleanup {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
for _, d := range s.disks {
|
||||
|
||||
ui.Say(fmt.Sprintf("Waiting for disk %q detach to complete", d))
|
||||
err := NewDiskAttacher(azcli).WaitForDetach(context.Background(), d.String())
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("error detaching disk %q: %s", d, err))
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Deleting disk %q", d))
|
||||
|
||||
f, err := azcli.DisksClient().Delete(context.TODO(), d.ResourceGroup, d.ResourceName.String())
|
||||
if err == nil {
|
||||
err = f.WaitForCompletionRef(context.TODO(), azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateNewDiskset.Cleanup: error: %+v", err)
|
||||
ui.Error(fmt.Sprintf("error deleting disk '%s': %v.", d, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"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-12-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
func TestStepCreateNewDisk_Run(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fields StepCreateNewDiskset
|
||||
expectedPutDiskBodies []string
|
||||
want multistep.StepAction
|
||||
verifyDiskset *Diskset
|
||||
}{
|
||||
{
|
||||
name: "from disk",
|
||||
fields: StepCreateNewDiskset{
|
||||
OSDiskID: "/subscriptions/SubscriptionID/resourcegroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName",
|
||||
OSDiskSizeGB: 42,
|
||||
OSDiskStorageAccountType: string(compute.PremiumLRS),
|
||||
HyperVGeneration: string(compute.V1),
|
||||
Location: "westus",
|
||||
SourceOSDiskResourceID: "SourceDisk",
|
||||
},
|
||||
expectedPutDiskBodies: []string{`
|
||||
{
|
||||
"location": "westus",
|
||||
"properties": {
|
||||
"osType": "Linux",
|
||||
"hyperVGeneration": "V1",
|
||||
"creationData": {
|
||||
"createOption": "Copy",
|
||||
"sourceResourceId": "SourceDisk"
|
||||
},
|
||||
"diskSizeGB": 42
|
||||
},
|
||||
"sku": {
|
||||
"name": "Premium_LRS"
|
||||
}
|
||||
}`},
|
||||
want: multistep.ActionContinue,
|
||||
verifyDiskset: &Diskset{-1: resource("/subscriptions/SubscriptionID/resourceGroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName")},
|
||||
},
|
||||
{
|
||||
name: "from platform image",
|
||||
fields: StepCreateNewDiskset{
|
||||
OSDiskID: "/subscriptions/SubscriptionID/resourcegroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName",
|
||||
OSDiskStorageAccountType: string(compute.StandardLRS),
|
||||
HyperVGeneration: string(compute.V1),
|
||||
Location: "westus",
|
||||
SourcePlatformImage: &client.PlatformImage{
|
||||
Publisher: "Microsoft",
|
||||
Offer: "Windows",
|
||||
Sku: "2016-DataCenter",
|
||||
Version: "2016.1.4",
|
||||
},
|
||||
},
|
||||
expectedPutDiskBodies: []string{`
|
||||
{
|
||||
"location": "westus",
|
||||
"properties": {
|
||||
"osType": "Linux",
|
||||
"hyperVGeneration": "V1",
|
||||
"creationData": {
|
||||
"createOption":"FromImage",
|
||||
"imageReference": {
|
||||
"id":"/subscriptions/SubscriptionID/providers/Microsoft.Compute/locations/westus/publishers/Microsoft/artifacttypes/vmimage/offers/Windows/skus/2016-DataCenter/versions/2016.1.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sku": {
|
||||
"name": "Standard_LRS"
|
||||
}
|
||||
}`},
|
||||
want: multistep.ActionContinue,
|
||||
verifyDiskset: &Diskset{-1: resource("/subscriptions/SubscriptionID/resourceGroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName")},
|
||||
},
|
||||
{
|
||||
name: "from shared image",
|
||||
fields: StepCreateNewDiskset{
|
||||
OSDiskID: "/subscriptions/SubscriptionID/resourcegroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName",
|
||||
OSDiskStorageAccountType: string(compute.StandardLRS),
|
||||
DataDiskStorageAccountType: string(compute.PremiumLRS),
|
||||
DataDiskIDPrefix: "/subscriptions/SubscriptionID/resourcegroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryDataDisk-",
|
||||
HyperVGeneration: string(compute.V1),
|
||||
Location: "westus",
|
||||
SourceImageResourceID: "/subscriptions/SubscriptionID/resourcegroups/imagegroup/providers/Microsoft.Compute/galleries/MyGallery/images/MyImage/versions/1.2.3",
|
||||
},
|
||||
|
||||
expectedPutDiskBodies: []string{`
|
||||
{
|
||||
"location": "westus",
|
||||
"properties": {
|
||||
"osType": "Linux",
|
||||
"hyperVGeneration": "V1",
|
||||
"creationData": {
|
||||
"createOption":"FromImage",
|
||||
"galleryImageReference": {
|
||||
"id":"/subscriptions/SubscriptionID/resourcegroups/imagegroup/providers/Microsoft.Compute/galleries/MyGallery/images/MyImage/versions/1.2.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sku": {
|
||||
"name": "Standard_LRS"
|
||||
}
|
||||
}`, `
|
||||
{
|
||||
"location": "westus",
|
||||
"properties": {
|
||||
"creationData": {
|
||||
"createOption":"FromImage",
|
||||
"galleryImageReference": {
|
||||
"id": "/subscriptions/SubscriptionID/resourcegroups/imagegroup/providers/Microsoft.Compute/galleries/MyGallery/images/MyImage/versions/1.2.3",
|
||||
"lun": 5
|
||||
}
|
||||
}
|
||||
},
|
||||
"sku": {
|
||||
"name": "Premium_LRS"
|
||||
}
|
||||
}`, `
|
||||
{
|
||||
"location": "westus",
|
||||
"properties": {
|
||||
"creationData": {
|
||||
"createOption":"FromImage",
|
||||
"galleryImageReference": {
|
||||
"id": "/subscriptions/SubscriptionID/resourcegroups/imagegroup/providers/Microsoft.Compute/galleries/MyGallery/images/MyImage/versions/1.2.3",
|
||||
"lun": 9
|
||||
}
|
||||
}
|
||||
},
|
||||
"sku": {
|
||||
"name": "Premium_LRS"
|
||||
}
|
||||
}`, `
|
||||
{
|
||||
"location": "westus",
|
||||
"properties": {
|
||||
"creationData": {
|
||||
"createOption":"FromImage",
|
||||
"galleryImageReference": {
|
||||
"id": "/subscriptions/SubscriptionID/resourcegroups/imagegroup/providers/Microsoft.Compute/galleries/MyGallery/images/MyImage/versions/1.2.3",
|
||||
"lun": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
"sku": {
|
||||
"name": "Premium_LRS"
|
||||
}
|
||||
}`},
|
||||
want: multistep.ActionContinue,
|
||||
verifyDiskset: &Diskset{
|
||||
-1: resource("/subscriptions/SubscriptionID/resourceGroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryOSDiskName"),
|
||||
3: resource("/subscriptions/SubscriptionID/resourceGroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryDataDisk-3"),
|
||||
5: resource("/subscriptions/SubscriptionID/resourceGroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryDataDisk-5"),
|
||||
9: resource("/subscriptions/SubscriptionID/resourceGroups/ResourceGroupName/providers/Microsoft.Compute/disks/TemporaryDataDisk-9"),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := tt.fields
|
||||
|
||||
bodyCount := 0
|
||||
m := compute.NewDisksClient("SubscriptionID")
|
||||
m.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if r.Method != "PUT" {
|
||||
t.Fatal("Expected only a PUT disk call")
|
||||
}
|
||||
b, _ := ioutil.ReadAll(r.Body)
|
||||
expectedPutDiskBody := regexp.MustCompile(`[\s\n]`).ReplaceAllString(tt.expectedPutDiskBodies[bodyCount], "")
|
||||
bodyCount++
|
||||
if string(b) != expectedPutDiskBody {
|
||||
t.Fatalf("expected body #%d to be %q, but got %q", bodyCount, expectedPutDiskBody, string(b))
|
||||
}
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
})
|
||||
|
||||
giv := compute.NewGalleryImageVersionsClient("SubscriptionID")
|
||||
giv.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if r.Method == "GET" &&
|
||||
regexp.MustCompile(`(?i)/versions/1\.2\.3$`).MatchString(r.URL.Path) {
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{
|
||||
"properties": { "storageProfile": {
|
||||
"dataDiskImages":[
|
||||
{ "lun": 5 },
|
||||
{ "lun": 9 },
|
||||
{ "lun": 3 }
|
||||
]
|
||||
} }
|
||||
}`)),
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
}
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Status: "Unexpected request",
|
||||
StatusCode: 500,
|
||||
}, nil
|
||||
})
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
SubscriptionIDMock: "SubscriptionID",
|
||||
DisksClientMock: m,
|
||||
GalleryImageVersionsClientMock: giv,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
|
||||
if got := s.Run(context.TODO(), state); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("StepCreateNewDisk.Run() = %v, want %v", got, tt.want)
|
||||
}
|
||||
|
||||
ds := state.Get(stateBagKey_Diskset)
|
||||
if tt.verifyDiskset != nil && !reflect.DeepEqual(*tt.verifyDiskset, ds) {
|
||||
t.Errorf("Error verifying diskset after Run(), got %v, want %v", ds, *tt.verifyDiskset)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func resource(id string) client.Resource {
|
||||
v, err := client.ParseResourceID(id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
@@ -4,10 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"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"
|
||||
@@ -15,20 +13,19 @@ import (
|
||||
)
|
||||
|
||||
type StepCreateSharedImageVersion struct {
|
||||
Destination SharedImageGalleryDestination
|
||||
OSDiskCacheType string
|
||||
DataDiskCacheType string
|
||||
Location string
|
||||
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)
|
||||
snapshotset := state.Get(stateBagKey_Snapshotset).(Diskset)
|
||||
osDiskSnapshotResourceID := state.Get(stateBagKey_OSDiskSnapshotResourceID).(string)
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating image version %s\n using %q for os disk.",
|
||||
ui.Say(fmt.Sprintf("Creating image version %s\n using %s for os disk.",
|
||||
s.Destination.ResourceID(azcli.SubscriptionID()),
|
||||
snapshotset.OS()))
|
||||
osDiskSnapshotResourceID))
|
||||
|
||||
var targetRegions []compute.TargetRegion
|
||||
// transform target regions to API objects
|
||||
@@ -46,7 +43,7 @@ func (s *StepCreateSharedImageVersion) Run(ctx context.Context, state multistep.
|
||||
GalleryImageVersionProperties: &compute.GalleryImageVersionProperties{
|
||||
StorageProfile: &compute.GalleryImageVersionStorageProfile{
|
||||
OsDiskImage: &compute.GalleryOSDiskImage{
|
||||
Source: &compute.GalleryArtifactVersionSource{ID: to.StringPtr(snapshotset.OS().String())},
|
||||
Source: &compute.GalleryArtifactVersionSource{ID: &osDiskSnapshotResourceID},
|
||||
HostCaching: compute.HostCaching(s.OSDiskCacheType),
|
||||
},
|
||||
},
|
||||
@@ -57,26 +54,6 @@ func (s *StepCreateSharedImageVersion) Run(ctx context.Context, state multistep.
|
||||
},
|
||||
}
|
||||
|
||||
var datadisks []compute.GalleryDataDiskImage
|
||||
for lun, resource := range snapshotset {
|
||||
if lun != -1 {
|
||||
ui.Say(fmt.Sprintf(" using %q for data disk (lun %d).", resource, lun))
|
||||
|
||||
datadisks = append(datadisks, compute.GalleryDataDiskImage{
|
||||
Lun: to.Int32Ptr(lun),
|
||||
Source: &compute.GalleryArtifactVersionSource{ID: to.StringPtr(resource.String())},
|
||||
HostCaching: compute.HostCaching(s.DataDiskCacheType),
|
||||
})
|
||||
}
|
||||
}
|
||||
if datadisks != nil {
|
||||
// sort by lun
|
||||
sort.Slice(datadisks, func(i, j int) bool {
|
||||
return *datadisks[i].Lun < *datadisks[j].Lun
|
||||
})
|
||||
imageVersion.GalleryImageVersionProperties.StorageProfile.DataDiskImages = &datadisks
|
||||
}
|
||||
|
||||
f, err := azcli.GalleryImageVersionsClient().CreateOrUpdate(
|
||||
ctx,
|
||||
s.Destination.ResourceGroup,
|
||||
@@ -86,11 +63,7 @@ func (s *StepCreateSharedImageVersion) Run(ctx context.Context, state multistep.
|
||||
imageVersion)
|
||||
if err == nil {
|
||||
log.Println("Shared image version creation in process...")
|
||||
pollClient := azcli.PollClient()
|
||||
pollClient.PollingDelay = 10 * time.Second
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Hour*12)
|
||||
defer cancel()
|
||||
err = f.WaitForCompletionRef(ctx, pollClient)
|
||||
err = f.WaitForCompletionRef(ctx, azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateSharedImageVersion.Run: error: %+v", err)
|
||||
|
||||
@@ -12,21 +12,19 @@ import (
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"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
|
||||
DataDiskCacheType string
|
||||
Location string
|
||||
Destination SharedImageGalleryDestination
|
||||
OSDiskCacheType string
|
||||
Location string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
snapshotset Diskset
|
||||
want multistep.StepAction
|
||||
expectedPutBody string
|
||||
}{
|
||||
@@ -39,7 +37,7 @@ func TestStepCreateSharedImageVersion_Run(t *testing.T) {
|
||||
ImageName: "ImageName",
|
||||
ImageVersion: "0.1.2",
|
||||
TargetRegions: []TargetRegion{
|
||||
{
|
||||
TargetRegion{
|
||||
Name: "region1",
|
||||
ReplicaCount: 5,
|
||||
StorageAccountType: "Standard_ZRS",
|
||||
@@ -47,15 +45,8 @@ func TestStepCreateSharedImageVersion_Run(t *testing.T) {
|
||||
},
|
||||
ExcludeFromLatest: true,
|
||||
},
|
||||
OSDiskCacheType: "ReadWrite",
|
||||
DataDiskCacheType: "None",
|
||||
Location: "region2",
|
||||
Location: "region2",
|
||||
},
|
||||
snapshotset: diskset(
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/snapshots/osdisksnapshot",
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/snapshots/datadisksnapshot0",
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/snapshots/datadisksnapshot1",
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/snapshots/datadisksnapshot2"),
|
||||
expectedPutBody: `{
|
||||
"location": "region2",
|
||||
"properties": {
|
||||
@@ -71,34 +62,10 @@ func TestStepCreateSharedImageVersion_Run(t *testing.T) {
|
||||
},
|
||||
"storageProfile": {
|
||||
"osDiskImage": {
|
||||
"hostCaching": "ReadWrite",
|
||||
"source": {
|
||||
"id": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/snapshots/osdisksnapshot"
|
||||
"id": "osdisksnapshotresourceid"
|
||||
}
|
||||
},
|
||||
"dataDiskImages": [
|
||||
{
|
||||
"lun": 0,
|
||||
"hostCaching": "None",
|
||||
"source": {
|
||||
"id": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/snapshots/datadisksnapshot0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"lun": 1,
|
||||
"hostCaching": "None",
|
||||
"source": {
|
||||
"id": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/snapshots/datadisksnapshot1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"lun": 2,
|
||||
"hostCaching": "None",
|
||||
"source": {
|
||||
"id": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/snapshots/datadisksnapshot2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`,
|
||||
@@ -127,14 +94,13 @@ func TestStepCreateSharedImageVersion_Run(t *testing.T) {
|
||||
GalleryImageVersionsClientMock: m,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
state.Put(stateBagKey_Snapshotset, tt.snapshotset)
|
||||
state.Put(stateBagKey_OSDiskSnapshotResourceID, "osdisksnapshotresourceid")
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StepCreateSharedImageVersion{
|
||||
Destination: tt.fields.Destination,
|
||||
OSDiskCacheType: tt.fields.OSDiskCacheType,
|
||||
DataDiskCacheType: tt.fields.DataDiskCacheType,
|
||||
Location: tt.fields.Location,
|
||||
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)
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
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-12-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
)
|
||||
|
||||
var _ multistep.Step = &StepCreateSnapshotset{}
|
||||
|
||||
type StepCreateSnapshotset struct {
|
||||
OSDiskSnapshotID string
|
||||
DataDiskSnapshotIDPrefix string
|
||||
Location string
|
||||
|
||||
SkipCleanup bool
|
||||
|
||||
snapshots Diskset
|
||||
}
|
||||
|
||||
func (s *StepCreateSnapshotset) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
diskset := state.Get(stateBagKey_Diskset).(Diskset)
|
||||
|
||||
s.snapshots = make(Diskset)
|
||||
|
||||
errorMessage := func(format string, params ...interface{}) multistep.StepAction {
|
||||
err := fmt.Errorf("StepCreateSnapshotset.Run: error: "+format, params...)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
for lun, resource := range diskset {
|
||||
snapshotID := fmt.Sprintf("%s%d", s.DataDiskSnapshotIDPrefix, lun)
|
||||
if lun == -1 {
|
||||
snapshotID = s.OSDiskSnapshotID
|
||||
}
|
||||
ssr, err := client.ParseResourceID(snapshotID)
|
||||
if err != nil {
|
||||
errorMessage("Could not create a valid resource id, tried %q: %v", snapshotID, err)
|
||||
}
|
||||
if !strings.EqualFold(ssr.Provider, "Microsoft.Compute") ||
|
||||
!strings.EqualFold(ssr.ResourceType.String(), "snapshots") {
|
||||
return errorMessage("Resource %q is not of type Microsoft.Compute/snapshots", snapshotID)
|
||||
}
|
||||
s.snapshots[lun] = ssr
|
||||
state.Put(stateBagKey_Snapshotset, s.snapshots)
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating snapshot %q", ssr))
|
||||
|
||||
snapshot := compute.Snapshot{
|
||||
Location: to.StringPtr(s.Location),
|
||||
SnapshotProperties: &compute.SnapshotProperties{
|
||||
CreationData: &compute.CreationData{
|
||||
CreateOption: compute.Copy,
|
||||
SourceResourceID: to.StringPtr(resource.String()),
|
||||
},
|
||||
Incremental: to.BoolPtr(false),
|
||||
},
|
||||
}
|
||||
|
||||
f, err := azcli.SnapshotsClient().CreateOrUpdate(ctx, ssr.ResourceGroup, ssr.ResourceName.String(), snapshot)
|
||||
if err != nil {
|
||||
return errorMessage("error initiating snapshot %q: %v", ssr, err)
|
||||
}
|
||||
|
||||
pollClient := azcli.PollClient()
|
||||
pollClient.PollingDelay = 2 * time.Second
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Hour*12)
|
||||
defer cancel()
|
||||
err = f.WaitForCompletionRef(ctx, pollClient)
|
||||
|
||||
if err != nil {
|
||||
return errorMessage("error creating snapshot '%s': %v", s.OSDiskSnapshotID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCreateSnapshotset) Cleanup(state multistep.StateBag) {
|
||||
if !s.SkipCleanup {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
for _, resource := range s.snapshots {
|
||||
|
||||
ui.Say(fmt.Sprintf("Removing any active SAS for snapshot %q", resource))
|
||||
{
|
||||
f, err := azcli.SnapshotsClient().RevokeAccess(context.TODO(), resource.ResourceGroup, resource.ResourceName.String())
|
||||
if err == nil {
|
||||
log.Printf("StepCreateSnapshotset.Cleanup: removing SAS...")
|
||||
err = f.WaitForCompletionRef(context.TODO(), azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateSnapshotset.Cleanup: error: %+v", err)
|
||||
ui.Error(fmt.Sprintf("error deleting snapshot %q: %v.", resource, err))
|
||||
}
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Deleting snapshot %q", resource))
|
||||
{
|
||||
f, err := azcli.SnapshotsClient().Delete(context.TODO(), resource.ResourceGroup, resource.ResourceName.String())
|
||||
if err == nil {
|
||||
log.Printf("StepCreateSnapshotset.Cleanup: deleting snapshot...")
|
||||
err = f.WaitForCompletionRef(context.TODO(), azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateSnapshotset.Cleanup: error: %+v", err)
|
||||
ui.Error(fmt.Sprintf("error deleting snapshot %q: %v.", resource, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-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 TestStepCreateSnapshot_Run(t *testing.T) {
|
||||
type fields struct {
|
||||
OSDiskSnapshotID string
|
||||
DataDiskSnapshotIDPrefix string
|
||||
Location string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
diskset Diskset
|
||||
want multistep.StepAction
|
||||
wantSnapshotset Diskset
|
||||
expectedPutBody string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
fields: fields{
|
||||
OSDiskSnapshotID: "/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/osdisk-snap",
|
||||
Location: "region1",
|
||||
},
|
||||
diskset: diskset("/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/disk1"),
|
||||
expectedPutBody: `{
|
||||
"location": "region1",
|
||||
"properties": {
|
||||
"creationData": {
|
||||
"createOption": "Copy",
|
||||
"sourceResourceId": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/disk1"
|
||||
},
|
||||
"incremental": false
|
||||
}
|
||||
}`,
|
||||
wantSnapshotset: diskset("/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/osdisk-snap"),
|
||||
},
|
||||
{
|
||||
name: "multi disk",
|
||||
fields: fields{
|
||||
OSDiskSnapshotID: "/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/osdisk-snap",
|
||||
DataDiskSnapshotIDPrefix: "/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datadisk-snap",
|
||||
Location: "region1",
|
||||
},
|
||||
diskset: diskset(
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/osdisk",
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/datadisk1",
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/datadisk2",
|
||||
"/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/datadisk3"),
|
||||
wantSnapshotset: diskset(
|
||||
"/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/osdisk-snap",
|
||||
"/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datadisk-snap0",
|
||||
"/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datadisk-snap1",
|
||||
"/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datadisk-snap2",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "invalid ResourceID",
|
||||
fields: fields{
|
||||
OSDiskSnapshotID: "notaresourceid",
|
||||
Location: "region1",
|
||||
},
|
||||
diskset: diskset("/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/disk1"),
|
||||
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")
|
||||
}
|
||||
if expectedPutBody != "" {
|
||||
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_Diskset, tt.diskset)
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StepCreateSnapshotset{
|
||||
OSDiskSnapshotID: tt.fields.OSDiskSnapshotID,
|
||||
DataDiskSnapshotIDPrefix: tt.fields.DataDiskSnapshotIDPrefix,
|
||||
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 len(tt.wantSnapshotset) > 0 {
|
||||
got := state.Get(stateBagKey_Snapshotset).(Diskset)
|
||||
if !reflect.DeepEqual(got, tt.wantSnapshotset) {
|
||||
t.Errorf("Snapshotset = %v, want %v", got, tt.wantSnapshotset)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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 := &StepCreateSnapshotset{
|
||||
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/ossnap/endGetAccess",
|
||||
"DELETE /subscriptions/subscriptionId/resourceGroups/rg/providers/Microsoft.Compute/snapshots/ossnap",
|
||||
"POST /subscriptions/subscriptionId/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datasnap1/endGetAccess",
|
||||
"DELETE /subscriptions/subscriptionId/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datasnap1",
|
||||
"POST /subscriptions/subscriptionId/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datasnap2/endGetAccess",
|
||||
"DELETE /subscriptions/subscriptionId/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datasnap2",
|
||||
}
|
||||
|
||||
m.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
got := r.Method + " " + r.URL.Path
|
||||
found := false
|
||||
for i, call := range expectedCalls {
|
||||
if call == got {
|
||||
// swap i with last and drop last
|
||||
expectedCalls[i] = expectedCalls[len(expectedCalls)-1]
|
||||
expectedCalls = expectedCalls[:len(expectedCalls)-1]
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("unexpected HTTP call: %v, wanted one of %q", got, expectedCalls)
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
StatusCode: 599, // 500 is retried
|
||||
}, nil
|
||||
}
|
||||
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 := &StepCreateSnapshotset{
|
||||
SkipCleanup: false,
|
||||
snapshots: diskset(
|
||||
"/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/ossnap",
|
||||
"/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datasnap1",
|
||||
"/subscriptions/1234/resourceGroups/rg/providers/Microsoft.Compute/snapshots/datasnap2"),
|
||||
}
|
||||
s.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepCreateSnapshotset_Cleanup(t *testing.T) {
|
||||
type fields struct {
|
||||
OSDiskSnapshotID string
|
||||
DataDiskSnapshotIDPrefix string
|
||||
Location string
|
||||
SkipCleanup bool
|
||||
snapshots Diskset
|
||||
}
|
||||
type args struct {
|
||||
state multistep.StateBag
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StepCreateSnapshotset{
|
||||
OSDiskSnapshotID: tt.fields.OSDiskSnapshotID,
|
||||
DataDiskSnapshotIDPrefix: tt.fields.DataDiskSnapshotIDPrefix,
|
||||
Location: tt.fields.Location,
|
||||
SkipCleanup: tt.fields.SkipCleanup,
|
||||
snapshots: tt.fields.snapshots,
|
||||
}
|
||||
s.Cleanup(tt.args.state)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,10 @@ import (
|
||||
"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"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
func TestStepResolvePlatformImageVersion_Run(t *testing.T) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"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"
|
||||
@@ -92,11 +92,6 @@ func (s *StepVerifySharedImageDestination) Run(ctx context.Context, state multis
|
||||
s.Image.GalleryName,
|
||||
s.Image.ImageName)
|
||||
|
||||
if err != nil {
|
||||
return errorMessage("Could not ListByGalleryImageComplete group:%v gallery:%v image:%v",
|
||||
s.Image.ResourceGroup, s.Image.GalleryName, s.Image.ImageName)
|
||||
}
|
||||
|
||||
for versions.NotDone() {
|
||||
version := versions.Value()
|
||||
|
||||
|
||||
@@ -8,12 +8,11 @@ import (
|
||||
"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"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
func TestStepVerifySharedImageDestination_Run(t *testing.T) {
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-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 = &StepVerifySharedImageSource{}
|
||||
|
||||
// StepVerifySharedImageSource verifies that the shared image location matches the Location field in the step.
|
||||
// Also verifies that the OS Type is Linux.
|
||||
type StepVerifySharedImageSource struct {
|
||||
SharedImageID string
|
||||
SubscriptionID string
|
||||
Location string
|
||||
}
|
||||
|
||||
// Run retrieves the image metadata from Azure and compares the location to Location. Verifies the OS Type.
|
||||
func (s *StepVerifySharedImageSource) 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("StepVerifySharedImageSource.Run: error: %+v", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
resource, err := client.ParseResourceID(s.SharedImageID)
|
||||
if err != nil {
|
||||
return errorMessage("Could not parse resource id %q: %w", s.SharedImageID, err)
|
||||
}
|
||||
|
||||
if !strings.EqualFold(resource.Provider, "Microsoft.Compute") ||
|
||||
!strings.EqualFold(resource.ResourceType.String(), "galleries/images/versions") {
|
||||
return errorMessage("Resource id %q does not identify a shared image version, expected Microsoft.Compute/galleries/images/versions", s.SharedImageID)
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Validating that shared image version %q exists",
|
||||
s.SharedImageID))
|
||||
|
||||
version, err := azcli.GalleryImageVersionsClient().Get(ctx,
|
||||
resource.ResourceGroup,
|
||||
resource.ResourceName[0],
|
||||
resource.ResourceName[1],
|
||||
resource.ResourceName[2],
|
||||
"")
|
||||
|
||||
if err != nil {
|
||||
return errorMessage("Error retrieving shared image version %q: %+v ", s.SharedImageID, err)
|
||||
}
|
||||
|
||||
if version.ID == nil || *version.ID == "" {
|
||||
return errorMessage("Error retrieving shared image version %q: ID field in response is empty", s.SharedImageID)
|
||||
}
|
||||
|
||||
if version.GalleryImageVersionProperties == nil ||
|
||||
version.GalleryImageVersionProperties.PublishingProfile == nil ||
|
||||
version.GalleryImageVersionProperties.PublishingProfile.TargetRegions == nil {
|
||||
return errorMessage("Could not retrieve shared image version properties for image %q.", s.SharedImageID)
|
||||
}
|
||||
|
||||
targetLocations := make([]string, 0, len(*version.GalleryImageVersionProperties.PublishingProfile.TargetRegions))
|
||||
vmLocation := client.NormalizeLocation(s.Location)
|
||||
locationFound := false
|
||||
for _, tr := range *version.GalleryImageVersionProperties.PublishingProfile.TargetRegions {
|
||||
l := to.String(tr.Name)
|
||||
l = client.NormalizeLocation(l)
|
||||
targetLocations = append(targetLocations, l)
|
||||
if strings.EqualFold(vmLocation, l) {
|
||||
locationFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !locationFound {
|
||||
return errorMessage("Target locations %q for %q does not include VM location %q",
|
||||
targetLocations, s.SharedImageID, vmLocation)
|
||||
}
|
||||
|
||||
imageResource, _ := resource.Parent()
|
||||
image, err := azcli.GalleryImagesClient().Get(ctx,
|
||||
resource.ResourceGroup,
|
||||
resource.ResourceName[0],
|
||||
resource.ResourceName[1])
|
||||
|
||||
if err != nil {
|
||||
return errorMessage("Error retrieving shared image %q: %+v ", imageResource.String(), err)
|
||||
}
|
||||
|
||||
if image.ID == nil || *image.ID == "" {
|
||||
return errorMessage("Error retrieving shared image %q: ID field in response is empty", imageResource.String())
|
||||
}
|
||||
|
||||
if image.GalleryImageProperties == nil {
|
||||
return errorMessage("Could not retrieve shared image properties for image %q.", imageResource.String())
|
||||
}
|
||||
|
||||
log.Printf("StepVerifySharedImageSource:Run: Image %q, HvGen: %q, osState: %q",
|
||||
to.String(image.ID),
|
||||
image.GalleryImageProperties.HyperVGeneration,
|
||||
image.GalleryImageProperties.OsState)
|
||||
|
||||
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 source image version %q, available in location %s",
|
||||
s.SharedImageID,
|
||||
s.Location))
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (*StepVerifySharedImageSource) Cleanup(multistep.StateBag) {}
|
||||
@@ -1,188 +0,0 @@
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-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 TestStepVerifySharedImageSource_Run(t *testing.T) {
|
||||
type fields struct {
|
||||
SharedImageID string
|
||||
SubscriptionID string
|
||||
Location string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want multistep.StepAction
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
fields: fields{
|
||||
SharedImageID: "/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/galleries/myGallery/images/myImage/versions/1.2.3",
|
||||
Location: "VM location",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "resource is not a shared image",
|
||||
fields: fields{
|
||||
SharedImageID: "/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/disks/myDisk",
|
||||
Location: "VM location",
|
||||
},
|
||||
want: multistep.ActionHalt,
|
||||
wantErr: "does not identify a shared image version",
|
||||
},
|
||||
{
|
||||
name: "error in resource id",
|
||||
fields: fields{
|
||||
SharedImageID: "not-a-resource-id",
|
||||
},
|
||||
want: multistep.ActionHalt,
|
||||
wantErr: "Could not parse resource id",
|
||||
},
|
||||
{
|
||||
name: "wrong location",
|
||||
fields: fields{
|
||||
SharedImageID: "/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/galleries/myGallery/images/myImage/versions/1.2.3",
|
||||
Location: "other location",
|
||||
},
|
||||
want: multistep.ActionHalt,
|
||||
wantErr: "does not include VM location",
|
||||
},
|
||||
{
|
||||
name: "image not found",
|
||||
fields: fields{
|
||||
SharedImageID: "/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/galleries/myGallery/images/myImage/versions/2.3.4",
|
||||
Location: "vm location",
|
||||
},
|
||||
want: multistep.ActionHalt,
|
||||
wantErr: "Error retrieving shared image version",
|
||||
},
|
||||
{
|
||||
name: "windows image",
|
||||
fields: fields{
|
||||
SharedImageID: "/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/galleries/myGallery/images/windowsImage/versions/1.2.3",
|
||||
Location: "VM location",
|
||||
},
|
||||
want: multistep.ActionHalt,
|
||||
wantErr: "not a Linux image",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
giv := compute.NewGalleryImageVersionsClient("subscriptionID")
|
||||
giv.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if r.Method == "GET" {
|
||||
switch {
|
||||
case strings.HasSuffix(r.URL.Path, "/versions/1.2.3"):
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{
|
||||
"id": "image-version-id",
|
||||
"properties": {
|
||||
"publishingProfile": {
|
||||
"targetRegions": [
|
||||
{ "name": "vm Location" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}`)),
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
case regexp.MustCompile(`(?i)^/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/galleries/myGallery/images/myImage/versions/\d+\.\d+\.\d+$`).
|
||||
MatchString(r.URL.Path):
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{"error":{"code":"NotFound"}}`)),
|
||||
StatusCode: 404,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
t.Errorf("Unexpected HTTP call: %s %s", r.Method, r.URL.RequestURI())
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Status: "Unexpected HTTP call",
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{"code":"TestError"}`)),
|
||||
StatusCode: 599,
|
||||
}, nil
|
||||
})
|
||||
|
||||
gi := compute.NewGalleryImagesClient("subscriptionID")
|
||||
gi.Sender = autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if r.Method == "GET" {
|
||||
switch {
|
||||
case strings.HasSuffix(r.URL.Path, "/images/myImage"):
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{
|
||||
"id": "image-id",
|
||||
"properties": {
|
||||
"osType": "Linux"
|
||||
}
|
||||
}`)),
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
case strings.HasSuffix(r.URL.Path, "/images/windowsImage"):
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{
|
||||
"id": "image-id",
|
||||
"properties": {
|
||||
"osType": "Windows"
|
||||
}
|
||||
}`)),
|
||||
StatusCode: 200,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
t.Errorf("Unexpected HTTP call: %s %s", r.Method, r.URL.RequestURI())
|
||||
return &http.Response{
|
||||
Request: r,
|
||||
Status: "Unexpected HTTP call",
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{"error":{"code":"TestError"}}`)),
|
||||
StatusCode: 599,
|
||||
}, nil
|
||||
})
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
SubscriptionIDMock: "subscriptionID",
|
||||
GalleryImageVersionsClientMock: giv,
|
||||
GalleryImagesClientMock: gi,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StepVerifySharedImageSource{
|
||||
SharedImageID: tt.fields.SharedImageID,
|
||||
SubscriptionID: tt.fields.SubscriptionID,
|
||||
Location: tt.fields.Location,
|
||||
}
|
||||
if got := s.Run(context.TODO(), state); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("StepVerifySharedImageSource.Run() = %v, want %v", got, tt.want)
|
||||
}
|
||||
d, _ := state.GetOk("error")
|
||||
err, _ := d.(error)
|
||||
if tt.wantErr != "" {
|
||||
if !strings.Contains(err.Error(), tt.wantErr) {
|
||||
t.Errorf("Wanted error %q, got %q", tt.wantErr, err)
|
||||
}
|
||||
} else if err != nil && err.Error() != "" {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/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"
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
|
||||
"github.com/hashicorp/packer/helper/useragent"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/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"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute/computeapi"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute/computeapi"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
// Config allows for various ways to authenticate Azure clients.
|
||||
// When `client_id` and `subscription_id` are specified, Packer will use the
|
||||
// specified Azure Active Directory (AAD) Service Principal (SP).
|
||||
// specified Azure Active Directoty (AAD) Service Principal (SP).
|
||||
// If only `subscription_id` is specified, Packer will try to interactively
|
||||
// log on the current user (tokens will be cached).
|
||||
// If none of these options are specified, Packer will attempt to use the
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package client
|
||||
|
||||
import "strings"
|
||||
|
||||
// NormalizeLocation returns a normalized location string.
|
||||
// Strings are converted to lower case and spaces are removed.
|
||||
func NormalizeLocation(loc string) string {
|
||||
return strings.ReplaceAll(strings.ToLower(loc), " ", "")
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package client
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNormalizeLocation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
loc string
|
||||
want string
|
||||
}{
|
||||
{"removes spaces", " with spaces ", "withspaces"},
|
||||
{"makes lowercase", "MiXed Case", "mixedcase"},
|
||||
{"North East US", "North East US", "northeastus"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := NormalizeLocation(tt.loc); got != tt.want {
|
||||
t.Errorf("NormalizeLocation() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/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"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParseResourceID parses an Azure resource ID
|
||||
func ParseResourceID(resourceID string) (Resource, error) {
|
||||
resourceID = strings.Trim(resourceID, "/")
|
||||
segments := strings.Split(resourceID, "/")
|
||||
if len(segments)%2 != 0 {
|
||||
return Resource{}, errors.New("Expected even number of segments")
|
||||
}
|
||||
|
||||
npairs := len(segments) / 2
|
||||
|
||||
keys := make([]string, npairs)
|
||||
values := make([]string, npairs)
|
||||
for i := 0; i < len(segments); i += 2 {
|
||||
keys[i/2] = segments[i]
|
||||
values[i/2] = segments[i+1]
|
||||
|
||||
if keys[i/2] == "" {
|
||||
return Resource{}, fmt.Errorf("Found empty segment (%d)", i)
|
||||
}
|
||||
if values[i/2] == "" {
|
||||
return Resource{}, fmt.Errorf("Found empty segment (%d)", i+1)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.EqualFold(keys[0], "subscriptions") {
|
||||
return Resource{}, fmt.Errorf("Expected first segment to be 'subscriptions', but found %q", keys[0])
|
||||
}
|
||||
|
||||
if !strings.EqualFold(keys[1], "resourceGroups") {
|
||||
return Resource{}, fmt.Errorf("Expected second segment to be 'resourceGroups', but found %q", keys[1])
|
||||
}
|
||||
|
||||
if !strings.EqualFold(keys[2], "providers") {
|
||||
return Resource{}, fmt.Errorf("Expected third segment to be 'providers', but found %q", keys[1])
|
||||
}
|
||||
|
||||
r := Resource{
|
||||
values[0],
|
||||
values[1],
|
||||
values[2],
|
||||
CompoundName(keys[3:]),
|
||||
CompoundName(values[3:]),
|
||||
}
|
||||
if err := r.Validate(); err != nil {
|
||||
return Resource{}, fmt.Errorf("Error validating resource: %w", err)
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
type Resource struct {
|
||||
Subscription string
|
||||
ResourceGroup string
|
||||
Provider string
|
||||
ResourceType CompoundName
|
||||
ResourceName CompoundName
|
||||
}
|
||||
|
||||
func (r Resource) String() string {
|
||||
return fmt.Sprintf(
|
||||
"/subscriptions/%s"+
|
||||
"/resourceGroups/%s"+
|
||||
"/providers/%s"+
|
||||
"/%s",
|
||||
r.Subscription,
|
||||
r.ResourceGroup,
|
||||
r.Provider,
|
||||
strings.Join(zipstrings(r.ResourceType, r.ResourceName), "/"))
|
||||
}
|
||||
|
||||
func (r Resource) Validate() error {
|
||||
if r.Subscription == "" {
|
||||
return errors.New("subscription is not set")
|
||||
}
|
||||
if r.ResourceGroup == "" {
|
||||
return errors.New("resource group is not set")
|
||||
}
|
||||
if r.Provider == "" {
|
||||
return errors.New("provider is not set")
|
||||
}
|
||||
if len(r.ResourceType) > len(r.ResourceName) {
|
||||
return errors.New("not enough values in resource name")
|
||||
}
|
||||
if len(r.ResourceType) < len(r.ResourceName) {
|
||||
return errors.New("too many values in resource name")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parent produces a resource ID representing the parent resource if this is a child resource
|
||||
func (r Resource) Parent() (Resource, error) {
|
||||
newLen := len(r.ResourceType) - 1
|
||||
if newLen == 0 {
|
||||
return Resource{}, errors.New("Top-level resource has no parent")
|
||||
}
|
||||
return Resource{
|
||||
Subscription: r.Subscription,
|
||||
ResourceGroup: r.ResourceGroup,
|
||||
Provider: r.Provider,
|
||||
ResourceType: r.ResourceType[:newLen],
|
||||
ResourceName: r.ResourceName[:newLen],
|
||||
}, nil
|
||||
}
|
||||
|
||||
type CompoundName []string
|
||||
|
||||
func (n CompoundName) String() string {
|
||||
return strings.Join(n, "/")
|
||||
}
|
||||
|
||||
func zipstrings(a []string, b []string) []string {
|
||||
c := make([]string, 0, len(a)+len(b))
|
||||
for i := 0; i < len(a) && i < len(b); i++ {
|
||||
c = append(c, a[i], b[i])
|
||||
}
|
||||
return c
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user