Compare commits

..

1 Commits

Author SHA1 Message Date
Wilken Rivera 79df21e271 Fix gosimple S1005 linting issue
Results before change
```
⇶  golangci-lint run ./... --disable-all --enable=gosimple | grep 1005
fix/fixer_comm_config.go:48:4: S1005: should write `sshHostPortMinRaw := builders["ssh_host_port_min"]` instead of `sshHostPortMinRaw, _ := builders["ssh_host_port_min"]` (gosimple)
fix/fixer_comm_config.go:64:4: S1005: should write `sshHostPortMaxRaw := builders["ssh_host_port_max"]` instead of `sshHostPortMaxRaw, _ := builders["ssh_host_port_max"]` (gosimple)
fix/fixer_comm_config.go:81:4: S1005: should write `sshSkipNatMappingRaw := builders["ssh_skip_nat_mapping"]` instead of `sshSkipNatMappingRaw, _ := builders["ssh_skip_nat_mapping"]` (gosimple)
packer/artifact_mock.go:47:2: S1005: should write `value := a.StateValues[name]` instead of `value, _ := a.StateValues[name]` (gosimple)
packer/artifact_test.go:31:2: S1005: should write `value := a.state[name]` instead of `value, _ := a.state[name]` (gosimple)
```

Results after change
```
```
2020-03-10 23:36:20 -04:00
5003 changed files with 260899 additions and 555245 deletions
+45 -74
View File
@@ -1,14 +1,11 @@
orbs:
win: circleci/windows@1.0.0
codecov: codecov/codecov@1.0.5
version: 2.1
executors:
golang:
docker:
- image: circleci/golang:1.13
resource_class: medium+
darwin:
macos:
xcode: "9.0"
@@ -23,7 +20,7 @@ commands:
steps:
- checkout
- run: curl https://dl.google.com/go/go<< parameters.GOVERSION >>.<< parameters.GOOS >>-amd64.tar.gz | tar -C ~/ -xz
- run: ~/go/bin/go test ./... -coverprofile=coverage.txt -covermode=atomic
- run: ~/go/bin/go test ./...
install-go-run-tests-windows:
parameters:
GOVERSION:
@@ -32,7 +29,7 @@ commands:
- checkout
- run: curl https://dl.google.com/go/go<< parameters.GOVERSION >>.windows-amd64.zip --output ~/go<< parameters.GOVERSION >>.windows-amd64.zip
- run: unzip ~/go<< parameters.GOVERSION >>.windows-amd64.zip -d ~/
- run: ~/go/bin/go test ./... -coverprofile=coverage.txt -covermode=atomic
- run: ~/go/bin/go test ./...
build-and-persist-packer-binary:
parameters:
GOOS:
@@ -52,13 +49,10 @@ commands:
jobs:
test-linux:
executor: golang
resource_class: large
working_directory: /go/src/github.com/hashicorp/packer
steps:
- checkout
- run: TESTARGS="-coverprofile=coverage.txt -covermode=atomic" make ci
- codecov/upload:
file: coverage.txt
- run: make ci
test-darwin:
executor: darwin
working_directory: ~/go/src/github.com/hashicorp/packer
@@ -68,8 +62,6 @@ jobs:
- install-go-run-tests-unix:
GOOS: darwin
GOVERSION: "1.13"
- codecov/upload:
file: coverage.txt
test-windows:
executor:
name: win/vs2019
@@ -77,17 +69,6 @@ jobs:
steps:
- install-go-run-tests-windows:
GOVERSION: "1.13"
- codecov/upload:
file: coverage.txt
check-lint:
executor: golang
resource_class: xlarge
steps:
- checkout
- run: git fetch --all
- run:
command: make ci-lint
no_output_timeout: 30m
check-vendor-vs-mod:
executor: golang
working_directory: /go/src/github.com/hashicorp/packer
@@ -151,43 +132,15 @@ jobs:
- store_artifacts:
path: ./pkg/
destination: /
build-website-docker-image:
publish-github-tag-release:
docker:
- image: circleci/buildpack-deps
shell: /usr/bin/env bash -euo pipefail -c
- image: cibuilds/github:0.10
working_directory: /go/src/github.com/hashicorp/packer
steps:
- checkout
- setup_remote_docker
- run:
name: Build Docker Image if Necessary
command: |
IMAGE_TAG=$(cat website/Dockerfile website/package-lock.json | sha256sum | awk '{print $1;}')
echo "Using $IMAGE_TAG"
if curl https://hub.docker.com/v2/repositories/hashicorp/packer-website/tags/$IMAGE_TAG -fsL > /dev/null; then
echo "Dependencies have not changed, not building a new website docker image."
else
cd website/
docker build -t hashicorp/packer-website:$IMAGE_TAG .
docker tag hashicorp/packer-website:$IMAGE_TAG hashicorp/packer-website:latest
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
- 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/
workflows:
version: 2
test:
@@ -197,18 +150,35 @@ workflows:
- test-windows
check-code:
jobs:
- check-lint
- check-vendor-vs-mod
- check-fmt
- check-generate
build_packer_binaries:
jobs:
- build_linux
- build_darwin
- build_windows
- build_freebsd
- build_openbsd
- build_solaris
- build_linux:
filters:
tags:
only: /.*/
- build_darwin:
filters:
tags:
only: /.*/
- build_windows:
filters:
tags:
only: /.*/
- build_freebsd:
filters:
tags:
only: /.*/
- build_openbsd:
filters:
tags:
only: /.*/
- build_solaris:
filters:
tags:
only: /.*/
- store_artifacts:
requires:
- build_linux
@@ -217,15 +187,16 @@ workflows:
- build_freebsd
- build_openbsd
- build_solaris
website:
jobs:
- build-website-docker-image:
- publish-github-tag-release:
requires:
- build_linux
- build_darwin
- build_windows
- build_freebsd
- build_openbsd
- build_solaris
filters:
branches:
only:
- master
- algolia-index:
filters:
branches:
only:
- stable-website
ignore: /.*/
tags:
only: nightly
-17
View File
@@ -1,17 +0,0 @@
comment:
layout: "flags, files"
behavior: default
require_changes: true # only comment on changes in coverage
require_base: yes # [yes :: must have a base report to post]
require_head: yes # [yes :: must have a head report to post]
after_n_builds: 3 # wait for all OS test coverage builds to post comment
branches: # branch names that can post comment
- "master"
coverage:
status:
project: off
patch: off
ignore: # ignore hcl2spec generated code for coverage
- "**/*.hcl2spec.go"
-1
View File
@@ -3,7 +3,6 @@
*.sh text eol=lf
*.json text eol=lf
*.md text eol=lf
*.mdx text eol=lf
*.ps1 text eol=lf
*.hcl text eol=lf
go.mod text eol=lf
+32 -243
View File
@@ -15,20 +15,20 @@ can quickly merge or address your contributions.
### Reporting an Issue
- Make sure you test against the latest released version. It is possible we
* Make sure you test against the latest released version. It is possible we
already fixed the bug you're experiencing.
- Run the command with debug output with the environment variable `PACKER_LOG`.
* Run the command with debug output with the environment variable `PACKER_LOG`.
For example: `PACKER_LOG=1 packer build template.json`. Take the _entire_
output and create a [gist](https://gist.github.com) for linking to in your
issue. Packer should strip sensitive keys from the output, but take a look
through just in case.
- Provide a reproducible test case. If a contributor can't reproduce an issue,
* Provide a reproducible test case. If a contributor can't reproduce an issue,
then it dramatically lowers the chances it'll get fixed. And in some cases,
the issue will eventually be closed.
- Respond promptly to any questions made by the Packer team to your issue. Stale
* Respond promptly to any questions made by the Packer team to your issue. Stale
issues will be closed.
### Issue Lifecycle
@@ -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
@@ -97,23 +86,23 @@ The instructions below are for go 1.7. or later.
submitting a pull-request.
### Windows Systems
On windows systems you need at least the [MinGW Tools](http://www.mingw.org/), e.g. install via [choco](https://chocolatey.org/):
```
choco install mingw -y
```
This installs the GCC compiler, as well as a `mingw32-make` which can be used wherever
this documentation mentions `make`
This installs the GCC compiler, as well as a ```mingw32-make``` which can be used wherever
this documentation mentions ```make```
when building using `go` you also need to mention the windows
when building using ```go``` you also need to mention the windows
executable extension
```
go build -o bin/packer.exe
```
### Opening an Pull Request
Thank you for contributing! When you are ready to open a pull-request, you will
@@ -142,36 +131,37 @@ to use `git push ...`.
### Pull Request Lifecycle
1. You are welcome to submit your pull request for commentary or review before
it is fully completed. Please prefix the title of your pull request with
"[WIP]" to indicate this. It's also a good idea to include specific questions
or items you'd like feedback on.
it is fully completed. Please prefix the title of your pull request with
"[WIP]" to indicate this. It's also a good idea to include specific questions
or items you'd like feedback on.
2. Once you believe your pull request is ready to be merged, you can remove any
"[WIP]" prefix from the title and a core team member will review.
"[WIP]" prefix from the title and a core team member will review.
3. One of Packer's core team members will look over your contribution and
either merge, or provide comments letting you know if there is anything left
to do. We do our best to provide feedback in a timely manner, but it may take
some time for us to respond. We may also have questions that we need answered
about the code, either because something doesn't make sense to us or because
we want to understand your thought process.
either merge, or provide comments letting you know if there is anything left
to do. We do our best to provide feedback in a timely manner, but it may take
some time for us to respond. We may also have questions that we need answered
about the code, either because something doesn't make sense to us or because
we want to understand your thought process.
4. If we have requested changes, you can either make those changes or, if you
disagree with the suggested changes, we can have a conversation about our
reasoning and agree on a path forward. This may be a multi-step process. Our
view is that pull requests are a chance to collaborate, and we welcome
conversations about how to do things better. It is the contributor's
responsibility to address any changes requested. While reviewers are happy to
give guidance, it is unsustainable for us to perform the coding work necessary
to get a PR into a mergeable state.
disagree with the suggested changes, we can have a conversation about our
reasoning and agree on a path forward. This may be a multi-step process. Our
view is that pull requests are a chance to collaborate, and we welcome
conversations about how to do things better. It is the contributor's
responsibility to address any changes requested. While reviewers are happy to
give guidance, it is unsustainable for us to perform the coding work necessary
to get a PR into a mergeable state.
5. Once all outstanding comments and checklist items have been addressed, your
contribution will be merged! Merged PRs will be included in the next
Packer release. The core team takes care of updating the
[CHANGELOG.md](../CHANGELOG.md) as they merge.
contribution will be merged! Merged PRs will be included in the next
Packer release. The core team takes care of updating the
[CHANGELOG.md](../CHANGELOG.md) as they merge.
6. In rare cases, we might decide that a PR should be closed without merging.
We'll make sure to provide clear reasoning when this happens.
We'll make sure to provide clear reasoning when this happens.
### Tips for Working on Packer
@@ -260,7 +250,7 @@ does not attempt to track the latest version for each dependency.
Packer relies on `go generate` to generate a [peg parser for boot
commands](https://github.com/hashicorp/packer/blob/master/common/bootcommand/boot_command.go),
[docs](https://github.com/hashicorp/packer/blob/master/website/pages/partials/builder/amazon/chroot/_Config-not-required.mdx)
[docs](https://github.com/hashicorp/packer/blob/master/website/source/partials/builder/amazon/chroot/_Config-not-required.html.md)
and HCL2's bridging code. Packer's testing suite will run `make check-generate`
to check that all the generated files Packer needs are what they should be.
`make generate` re-generates all these file and can take a while depending on
@@ -276,18 +266,16 @@ Packer relies on [golangci-lint](https://github.com/golangci/golangci-lint) for
The main configuration for golangci-lint is the `.golangci.yml` in the project root. See `golangci-lint --help` for a list of flags that can be used to override the default configuration.
Run golangci-lint on the entire Packer code base.
```
make lint
```
Run golangci-lint on a single pkg or directory; PKG_NAME expands to /builder/amazon/...
```
make lint PKG_NAME=builder/amazon
```
Note: linting on Travis uses the `--new-from-rev` flag to only lint new files added within a branch or pull-request. To run this check locally you can use the `ci-lint` make target. See [golangci-lint in CI](https://github.com/golangci/golangci-lint#faq) for more information.
Note: linting on Travis uses the `--new-from-rev=origin/master` flag to only lint new files added within a branch or pull-request. To run this check locally you can use the `ci-lint` make target. See [golangci-lint in CI](https://github.com/golangci/golangci-lint#faq) for more information.
```
make ci-lint
@@ -340,205 +328,6 @@ Acceptance tests typically require other environment variables to be set for
things such as API tokens and keys. Each test should error and tell you which
credentials are missing, so those are not documented here.
#### Running Provisioners Acceptance Tests
**Warning:** The acceptance tests create/destroy/modify _real resources_, which
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
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
tell which provisioner and builder the test should be run against.
Examples of usage:
- Run the Shell provisioner acceptance tests against the Amazon EBS builder.
```
ACC_TEST_BUILDERS=amazon-ebs ACC_TEST_PROVISIONERS=shell go test ./provisioner/shell/... -v -timeout=1h
```
- Do the same but using the Makefile
```
ACC_TEST_BUILDERS=amazon-ebs ACC_TEST_PROVISIONERS=shell make provisioners-acctest
```
- Run the all Shell and Powershell provisioners acceptance tests against the Amazon EBS builder.
```
ACC_TEST_BUILDERS=amazon-ebs ACC_TEST_PROVISIONERS=shell,powershell make provisioners-acctest
```
- Run the all provisioners acceptance tests against the Amazon EBS builder.
```
ACC_TEST_BUILDERS=amazon-ebs ACC_TEST_PROVISIONERS=all make provisioners-acctest
```
- Run the all provisioners acceptance tests against all builders whenever they are compatible.
```
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`)
#### 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.
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.
```go
type ProvisionerAcceptance interface {
GetName() string
GetConfig() (string, error)
GetProvisionerStore() packer.MapOfProvisioner
IsCompatible(builder string, vmOS string) bool
RunTest(c *command.BuildCommand, args []string) error
}
```
- **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.
For the Shell one the file contains:
```
{
"type": "shell",
"inline": [
"echo {{ build `ID`}} > provisioner.{{ build `PackerRunUUID`}}.txt"
]
},
{
"type": "file",
"source": "provisioner.{{ build `PackerRunUUID`}}.txt",
"destination": "provisioner.shell.{{ build `PackerRunUUID`}}.txt",
"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.
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.
For the Shell provisioners this is:
```go
func (s *ShellProvisionerAccTest) GetProvisionerStore() packer.MapOfProvisioner {
return packer.MapOfProvisioner{
"shell": func() (packer.Provisioner, error) { return &shell.Provisioner{}, nil },
"file": func() (packer.Provisioner, error) { return &file.Provisioner{}, nil },
}
}
```
- **IsCompatible(builder string, vmOS string)** returns true or false whether the provisioner should run against a
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:
```go
func (s *ShellProvisionerAccTest) RunTest(c *command.BuildCommand, args []string) error {
// Provisioner specific setup
UUID := os.Getenv("PACKER_RUN_UUID")
if UUID == "" {
UUID, _ = uuid.GenerateUUID()
os.Setenv("PACKER_RUN_UUID", UUID)
}
file := "provisioner.shell." + UUID + ".txt"
defer testshelper.CleanupFiles(file)
// 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)
out := ui.Writer.(*bytes.Buffer)
err := ui.ErrorWriter.(*bytes.Buffer)
return fmt.Errorf(
"Bad exit code.\n\nStdout:\n\n%s\n\nStderr:\n\n%s",
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:
```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.
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.
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
implement the BuilderAcceptance interface.
```go
type BuilderAcceptance interface {
GetConfigs() (map[string]string, error)
GetBuilderStore() packer.MapOfBuilder
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.
For the Amazon EBS builder the file contains:
```
{
"type": "amazon-ebs",
"ami_name": "packer-acc-test",
"instance_type": "m1.small",
"region": "us-east-1",
"ssh_username": "ubuntu",
"source_ami": "ami-0568456c",
"force_deregister" : true,
"tags": {
"packer-test": "true"
}
}
```
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`.
- **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 {
return packer.MapOfBuilder{
"amazon-ebs": func() (packer.Builder, error) { return &amazonebsbuilder.Builder{}, nil },
}
}
```
- **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`.
```go
var BuildersAccTest = map[string]BuilderAcceptance{
...
"amazon-ebs": new(amazonEBS.AmazonEBSAccTest),
...
}
```
Once you finish the steps, you should be ready to run your new provisioner acceptance test.
#### Debugging Plugins
Each packer plugin runs in a separate process and communicates via RPC over a
+1 -14
View File
@@ -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
+2 -2
View File
@@ -8,8 +8,8 @@ Issues on GitHub are intended to be related to bugs or feature requests, so we
recommend using our other community resources instead of asking here if you
have a question.
- Packer Guides: https://www.packer.io/guides
- Packer Guides: https://www.packer.io/guides/index.html
- Discussion List: https://groups.google.com/group/packer-tool
- Any other questions can be sent to the packer section of the HashiCorp
forum: https://discuss.hashicorp.com/c/packer
- Packer community links: https://www.packer.io/community
- Packer community links: https://www.packer.io/community.html
@@ -6,18 +6,19 @@ labels: communicator-question
Got one of the following errors ? See if the related guides can help.
- `Waiting for WinRM to become available` ?
* `Waiting for WinRM to become available` ?
- See our basic WinRm Packer guide: https://www.packer.io/guides/automatic-operating-system-installs/autounattend_windows
- See our basic WinRm Packer guide: https://www.packer.io/guides/automatic-operating-system-installs/autounattend_windows.html
- `Waiting for SSH to become available` ?
* `Waiting for SSH to become available` ?
- See our basic SSH Packer guide: https://www.packer.io/guides/automatic-operating-system-installs/preseed_ubuntu.html
- See our basic SSH Packer guide: https://www.packer.io/guides/automatic-operating-system-installs/preseed_ubuntu
Issues on GitHub are intended to be related to bugs or feature requests, so we recommend using our other community resources instead of asking here if you have a question.
- Packer Guides: https://www.packer.io/guides
- Packer Guides: https://www.packer.io/guides/index.html
- Discussion List: https://groups.google.com/group/packer-tool
- Any other questions can be sent to the packer section of the HashiCorp
forum: https://discuss.hashicorp.com/c/packer
- Packer community links: https://www.packer.io/community
- Packer community links: https://www.packer.io/community.html
-14
View File
@@ -1,14 +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
if: github.event.issue.pull_request == null
with:
repo-token: ${{ secrets.Github_Token }}
add-labels: "track-internal"
-1
View File
@@ -14,7 +14,6 @@ poll "closed_issue_locker" "locker" {
closed_for = "720h" # 30 days
max_issues = 500
sleep_between_issues = "5s"
no_comment_if_no_activity_for = "4320h" # 180 days
message = <<-EOF
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
+24
View File
@@ -0,0 +1,24 @@
env:
- USER=travis GO111MODULE=off
os:
- osx
language: go
branches:
only:
- master
jobs:
fast_finish: true
include:
- go: "1.13.x"
name: "go test"
script:
- df -h
- travis_wait make ci
- go: "1.13.x"
name: "go lint"
script: travis_wait make ci-lint
+16 -495
View File
@@ -1,490 +1,11 @@
## 1.6.2 (Upcoming)
## 1.5.5 (Upcoming)
### IMPROVEMENTS:
* builder/amazon: Add all of the custom AWS template engines to `build`
template function for use by provisioners. [GH-9751]
* builder/amazon: Add aws_polling config option to override env variables.
[GH-9777]
* builder/azure: Add FreeBSD support to azure/chroot builder. [GH-9697]
* builder/vmware-esx: Add `network_name` option to vmware so that users can set
a network without using vmx data. [GH-9718]
* builder/vmware: Add a `remote_output_directory option` so users can tell
Packer where on a datastore to create a vm. [GH-9784]
* builder/vmware: Add progress tracker to vmware-esx5 iso upload. [GH-9779]
* builder/vsphere: Add new `directory_permission` config export option.
[GH-9704]
* builder/vsphere: Add option to import OVF templates to the Content Library
[GH-9755]
* builder/vsphere: Add step and options to customize cloned VMs. [GH-9665]
* core/hcl: Add provisioner "override" option to HCL2 templates. [GH-9764]
* core/hcl: Add vault integration as an HCL2 function function. [GH-9746]
* core: Add colored prefix to progress bar so it's clearer what build each
progress bar belongs to. [GH-9780]
* core: Ui now pretty prints build durations. [GH-9749]
* core: When a build is cancelled, Packer will skip postprocessors gracefully
rather than failing them. [GH-9720]
* integrations/secretsmanager: Add support for plaintext non-key/pair secrets.
[GH-9773]
* post-processor/vsphere: Improve UI to catch bad credentials and print errors.
[GH-9649]
* provisioner/file: Clean up, bugfix, and document previously-hidden `sources`
option. [GH-9725] [GH-9735]
* provisioner/salt-masterless: Add option to option to download community
SaltStack formulas. [GH-9726]
### BUG FIXES:
* build: Fix bug in code generator that caused generation to fail in nested
packer/packer dirs [GH-9728]
* build: Fix Makefile so that default target doesn't crash and creates dev
binaries. [GH-9706]
* builder/amazon-ebssurrogate: Make skip_save_build_region option work in the
ebssurrogate builder, not just the ebs builder. [GH-9666]
* builder/file: Make sure that UploadDir receives the interpolated destination.
[GH-9698]
* builder/googlecompute: Fix bug where startup script hang would cause export
to hang. [GH-9708]
* builder/hyperv: Send boot command in small chunks to make it more stable.
[GH-9765]
* builder/scaleway: Fix config issue that made scaleway builder fail when used
with HCL2 config. [GH-9677]
* builder/vmware: Fully destroy vm if it was cancelled or errored. This will
make orphaned vms easier to destroy through vCenter. [GH-9782]
* builder/vsphere: Fix `alt`, `ctrl`, and `shift` keypresses in the
boot_command. [GH-9702] [GH-9739]
* builder/vsphere: Fix bug where Packer timed out if two interfaces were
defined but only one had an available IP. [GH-9748]
* builder/vsphere: Fix the configuration_parameters option so that it is always
applied, not just when the tool sync policy is set. [GH-9713]
* communicator: Fix `pause_before_connect` option to force a reconnect after
the pause. [GH-9772]
* core: Make `max_retries` provisioner option a string to allow variable
interpolation. [GH-9673]
* post-processor/vsphere-template: Fix ReregisterVM to default to true instead
of false. [GH-9736]
## 1.6.1 (July 30, 2020)
### 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]
### 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/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
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]
### 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]
* 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]
* provisioner/powershell: Fix integer decoding issue in the execution policy
parser [GH-8997]
## 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
initial device or device class used for booting the VM. [GH-8714]
* builder/hyperv: Fix Hyper-V compacted disk size comparison [GH-8811]
* 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
required [GH-8877]
* builder/vsphere-clone: Add ability to export VM to OVF file [GH-8764]
* builder/vsphere-iso: Add ability to define multiple disks. [GH-8787]
* builder/vsphere-iso: Add ability to export VM to OVF file [GH-8764]
* builder/vsphere-iso: Add support for eagerly zeroed / scrubbed disks.
[GH-8756]
* builder/vsphere-iso: Add the remote iso first so that it is first in boot
order, and clarify boot behavior. [GH-8732]
* communicator/ssh: Add flag to enable support for keyboard-interactive auth to
connect bastion [GH-8847]
* core/hcl2: Add support for singular blocks [GH-8889]
* core/hcl2: Add support in HCL2 configs for dynamic blocks, document for loops
and splat expressions [GH-8720]
* core/hcl2: Fix HCL2 local variables decoding to allow local usage within
another local in the same locals block [GH-8755]
* core/hcl2: Import new replace and regex_replace funcs from go-cty +
documentation [GH-8863]
* core: Enable hcl files as var files in HCL mode [GH-8882]
* core: Make "build" engine template variables SSHPublicKey and SSHPrivateKey
strings [GH-8829]
### Bug Fixes:
* 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]
* builder/azure: Fix HCL2 bug that prevented Azure and other builders from
loading properly. [GH-8785]
* builder/googlecompute: Fix WinRMPassword template engine. [GH-8890]
* builder/googlecompute: Replace deprecated "sshKeys" metadata with "ssh-keys"
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.
[GH-8828]
* builder/vsphere-clone: Fix issue preventing the cloning of VMs with the same
name in different folders [GH-8938]
* builder/vsphere-iso: Fix issue preventing the creation of VMs with the same
name in different folders [GH-8938]
* builder/vsphere: Fix network object interface panic. [GH-8753]
* core/hcl2: Fix crash when an unset variable is used [GH-8837]
* core/hcl2: Fix logic for parsing literal value variables [GH-8834]
* core/hcl2: Make sure locals are evaluated only after variables are. [GH-8918]
* core: Fix "build" template engine interpolation for certain fields in certain
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]
- builder/vsphere: Fix network object interface panic. [GH-8753]
## 1.5.4 (February 14, 2020)
no-change release to fix code-signing on OSX binaries. Since checksums for these
@@ -640,7 +161,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]
@@ -734,7 +255,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]
@@ -764,7 +285,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]
@@ -797,7 +318,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]
@@ -812,7 +333,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)
@@ -948,14 +469,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]
@@ -1192,7 +713,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]
@@ -1370,7 +891,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)
@@ -1443,7 +964,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]
@@ -1464,7 +985,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:
@@ -1606,7 +1127,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]
@@ -3727,7 +3248,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]
+22 -42
View File
@@ -2,84 +2,66 @@
# builders
/examples/alicloud/ @chhaj5236 @alexyueer
/builder/alicloud/ @chhaj5236 @alexyueer
/website/pages/docs/builders/alicloud* @chhaj5236 @alexyueer
/website/source/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
/website/source/docs/builders/azure* @paulmey
/builder/hyperv/ @taliesins
/website/pages/docs/builders/hyperv* @taliesins
/website/source/docs/builders/hyperv* @taliesins
/examples/jdcloud/ @XiaohanLiang @remrain
/builder/jdcloud/ @XiaohanLiang @remrain
/website/pages/docs/builders/jdcloud* @XiaohanLiang @remrain
/website/source/docs/builders/jdcloud* @XiaohanLiang @remrain
/builder/linode/ @displague @ctreatma @stvnjacobs @charliekenney23 @phillc
/website/pages/docs/builders/linode* @displague @ctreatma @stvnjacobs @charliekenney23 @phillc
/builder/linode/ @displague @ctreatma @stvnjacobs
/website/source/docs/builders/linode* @displague @ctreatma @stvnjacobs
/builder/lxc/ @ChrisLundquist
/website/pages/docs/builders/lxc* @ChrisLundquist
/test/fixtures/builder-lxc/ @ChrisLundquist
/test/builder_lxc* @ChrisLundquist
/website/source/docs/builders/lxc* @ChrisLundquist
/builder/lxd/ @ChrisLundquist
/website/pages/docs/builders/lxd* @ChrisLundquist
/website/source/docs/builders/lxd* @ChrisLundquist
/builder/oneandone/ @jasmingacic
/website/pages/docs/builders/oneandone* @jasmingacic
/website/source/docs/builders/oneandone* @jasmingacic
/builder/oracle/ @prydie @owainlewis
/website/pages/docs/builders/oracle* @prydie @owainlewis
/website/source/docs/builders/oracle* @prydie @owainlewis
/builder/profitbricks/ @jasmingacic
/website/pages/docs/builders/profitbricks* @jasmingacic
/website/source/docs/builders/profitbricks* @jasmingacic
/builder/triton/ @sean-
/website/pages/docs/builders/triton* @sean-
/website/source/docs/builders/triton* @sean-
/builder/ncloud/ @YuSungDuk
/website/pages/docs/builders/ncloud* @YuSungDuk
/website/source/docs/builders/ncloud* @YuSungDuk
/builder/proxmox/ @carlpett
/website/pages/docs/builders/proxmox* @carlpett
/website/source/docs/builders/proxmox* @carlpett
/builder/scaleway/ @sieben @mvaude @jqueuniet @fflorens @brmzkw
/website/pages/docs/builders/scaleway* @sieben @mvaude @jqueuniet @fflorens @brmzkw
/website/source/docs/builders/scaleway* @sieben @mvaude @jqueuniet @fflorens @brmzkw
/builder/hcloud/ @LKaemmerling
/website/pages/docs/builders/hcloud* @LKaemmerling
/website/source/docs/builders/hcloud* @LKaemmerling
/examples/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
/builder/hyperone/ @m110 @gregorybrzeski @ad-m
/website/source/docs/builders/hyperone* @m110 @gregorybrzeski @ad-m
/examples/ucloud/ @shawnmssu
/builder/ucloud/ @shawnmssu
/website/pages/docs/builders/ucloud* @shawnmssu
/website/source/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
/examples/tencentcloud/ @likexian
/builder/tencentcloud/ @likexian
/website/pages/docs/builders/tencentcloud* @likexian
/website/source/docs/builders/yandex* @GennadySpb @alexanderKhaustov @seukyaso
/builder/osc/ @marinsalinas
/website/source/docs/builders/osc* @marinsalinas
# provisioners
/examples/ansible/ @bhcleek
/provisioner/ansible/ @bhcleek
/provisioner/converge/ @stevendborrelli
@@ -89,7 +71,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
+9 -23
View File
@@ -1,7 +1,5 @@
TEST?=$(shell go list ./...)
VET?=$(shell go list ./...)
ACC_TEST_BUILDERS?=all
ACC_TEST_PROVISIONERS?=all
# Get the current full sha from git
GITSHA:=$(shell git rev-parse HEAD)
# Get the current local branch name from git (if we can, this may be blank)
@@ -16,16 +14,14 @@ EXECUTABLE_FILES=$(shell find . -type f -executable | egrep -v '^\./(website/[ve
GIT_DIRTY=$(shell test -n "`git status --porcelain`" && echo "+CHANGES" || true)
GIT_COMMIT=$(shell git rev-parse --short HEAD)
GIT_IMPORT=github.com/hashicorp/packer/version
UNAME_S := $(shell uname -s)
LDFLAGS=-s -w
GOLDFLAGS=-X $(GIT_IMPORT).GitCommit=$(GIT_COMMIT)$(GIT_DIRTY) $(LDFLAGS)
GOLDFLAGS=-X $(GIT_IMPORT).GitCommit=$(GIT_COMMIT)$(GIT_DIRTY)
export GOLDFLAGS
.PHONY: bin checkversion ci ci-lint default install-build-deps install-gen-deps fmt fmt-docs fmt-examples generate install-lint-deps lint \
releasebin test testacc testrace
default: install-build-deps install-gen-deps generate bin
default: install-build-deps install-gen-deps generate testrace dev releasebin package dev fmt fmt-check mode-check fmt-docs fmt-examples
ci: testrace ## Test in continuous integration
@@ -61,9 +57,8 @@ install-gen-deps: ## Install dependencies for code generation
@go install ./cmd/mapstructure-to-hcl2
install-lint-deps: ## Install linter dependencies
# Pinning golangci-lint at v1.23.8 as --new-from-rev seems to work properly; the latest 1.24.0 has caused issues with memory consumption
@echo "==> Updating linter dependencies..."
@curl -sSfL -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v1.23.8
@curl -sSfL -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v1.23.1
dev: ## Build and install a development build
@grep 'const VersionPrerelease = ""' version/version.go > /dev/null ; if [ $$? -eq 0 ]; then \
@@ -87,7 +82,8 @@ lint: install-lint-deps ## Lint Go code
ci-lint: install-lint-deps ## On ci only lint newly added Go source files
@echo "==> Running linter on newly added Go source files..."
GO111MODULE=on golangci-lint run --new-from-rev=$(shell git merge-base origin/master HEAD) ./...
GO111MODULE=on golangci-lint run --new-from-rev=origin/master ./...
fmt: ## Format Go code
@go fmt ./...
@@ -110,7 +106,7 @@ mode-check: ## Check that only certain files are executable
echo "Check passed."; \
fi
fmt-docs:
@find ./website/pages/docs -name "*.md" -exec pandoc --wrap auto --columns 79 --atx-headers -s -f "markdown_github+yaml_metadata_block" -t "markdown_github+yaml_metadata_block" {} -o {} \;
@find ./website/source/docs -name "*.md" -exec pandoc --wrap auto --columns 79 --atx-headers -s -f "markdown_github+yaml_metadata_block" -t "markdown_github+yaml_metadata_block" {} -o {} \;
# Install js-beautify with npm install -g js-beautify
fmt-examples:
@@ -120,12 +116,12 @@ 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/source/ -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
go fmt command/plugin.go
generate-check: generate ## Check go code generation is on par
@echo "==> Checking that auto-generated code is not changed..."
@@ -138,10 +134,6 @@ generate-check: generate ## Check go code generation is on par
test: mode-check vet ## Run unit tests
@go test $(TEST) $(TESTARGS) -timeout=3m
# acctest runs provisioners acceptance tests
provisioners-acctest: install-build-deps generate
ACC_TEST_BUILDERS=$(ACC_TEST_BUILDERS) ACC_TEST_PROVISIONERS=$(ACC_TEST_PROVISIONERS) go test ./provisioner/... -timeout=1h
# testacc runs acceptance tests
testacc: install-build-deps generate ## Run acceptance tests
@echo "WARN: Acceptance tests will take a long time to run and may cost money. Ctrl-C if you want to cancel."
@@ -150,12 +142,6 @@ testacc: install-build-deps generate ## Run acceptance tests
testrace: mode-check vet ## Test with race detection enabled
@GO111MODULE=off go test -race $(TEST) $(TESTARGS) -timeout=3m -p=8
# Runs code coverage and open a html page with report
cover:
go test $(TEST) $(TESTARGS) -timeout=3m -coverprofile=coverage.out
go tool cover -html=coverage.out
rm coverage.out
check-vendor-vs-mod: ## Check that go modules and vendored code are on par
@GO111MODULE=on go mod vendor
@git diff --exit-code --ignore-space-change --ignore-space-at-eol -- vendor ; if [ $$? -eq 1 ]; then \
+4 -22
View File
@@ -1,13 +1,12 @@
# Packer
[![Build Status][circleci-badge]][circleci]
[![Build Status][travis-badge]][travis]
[![Windows Build Status][appveyor-badge]][appveyor]
[![PkgGoDev](https://pkg.go.dev/badge/github.com/hashicorp/packer)](https://pkg.go.dev/github.com/hashicorp/packer)
[![GoDoc][godoc-badge]][godoc]
[![GoReportCard][report-badge]][report]
[![codecov](https://codecov.io/gh/hashicorp/packer/branch/master/graph/badge.svg)](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 +94,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/).
+35
View File
@@ -0,0 +1,35 @@
# appveyor.yml reference : http://www.appveyor.com/docs/appveyor-yml
version: "{build}"
skip_tags: true
branches:
only:
- master
os: Windows Server 2012 R2
environment:
GOPATH: c:\gopath
clone_folder: c:\gopath\src\github.com\hashicorp\packer
install:
- set GO111MODULE=off
- echo %Path%
- go version
- go env
build_script:
- git rev-parse HEAD
# go test $(go list ./... | grep -v vendor)
- ps: |
go.exe test -timeout=2m (go.exe list ./... `
|? { -not $_.Contains('/vendor/') } `
|? { $_ -ne 'github.com/hashicorp/packer/builder/parallels/common' } `
|? { $_ -ne 'github.com/hashicorp/packer/provisioner/ansible' })
test: off
deploy: off
+13 -13
View File
@@ -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`.
+102 -119
View File
@@ -3,21 +3,20 @@ package ecs
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/hcl2template"
"github.com/zclconf/go-cty/cty"
)
// 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 +46,98 @@ 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"`
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"`
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.
@@ -166,7 +157,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
@@ -188,8 +179,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"image_force_delete_snapshots": &hcldec.AttrSpec{Name: "image_force_delete_snapshots", Type: cty.Bool, Required: false},
"image_force_delete_instances": &hcldec.AttrSpec{Name: "image_force_delete_instances", Type: cty.Bool, Required: false},
"image_ignore_data_disks": &hcldec.AttrSpec{Name: "image_ignore_data_disks", Type: cty.Bool, Required: false},
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"system_disk_mapping": &hcldec.BlockSpec{TypeName: "system_disk_mapping", Nested: hcldec.ObjectSpec((*FlatAlicloudDiskDevice)(nil).HCL2Spec())},
"image_disk_mappings": &hcldec.BlockListSpec{TypeName: "image_disk_mappings", Nested: hcldec.ObjectSpec((*FlatAlicloudDiskDevice)(nil).HCL2Spec())},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
@@ -221,14 +211,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},
@@ -237,9 +223,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"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},
@@ -254,7 +238,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},
+47 -49
View File
@@ -7,7 +7,6 @@ import (
"regexp"
"strings"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/template/interpolate"
)
@@ -17,7 +16,7 @@ type AlicloudDiskDevice struct {
// 128] English or Chinese characters, must begin with an
// uppercase/lowercase letter or Chinese character. Can contain numbers,
// ., _ and -. The disk name will appear on the console. It cannot
// begin with `http://` or `https://`.
// begin with http:// or https://.
DiskName string `mapstructure:"disk_name" required:"false"`
// Category of the system disk. Optional values
// are:
@@ -35,7 +34,7 @@ type AlicloudDiskDevice struct {
SnapshotId string `mapstructure:"disk_snapshot_id" required:"false"`
// The value of disk description is blank by
// default. [2, 256] characters. The disk description will appear on the
// console. It cannot begin with `http://` or `https://`.
// console. It cannot begin with http:// or https://.
Description string `mapstructure:"disk_description" required:"false"`
// Whether or not the disk is
// released along with the instance:
@@ -61,9 +60,9 @@ type AlicloudDiskDevices struct {
// - `cloud_efficiency` - efficiency cloud disk
// - `cloud_ssd` - cloud SSD
//
// For phased-out instance types and non-I/O optimized instances, the
// default value is cloud. Otherwise, the default value is
// cloud\_efficiency.
// For phased-out instance types and non-I/O optimized instances, the
// default value is cloud. Otherwise, the default value is
// cloud\_efficiency.
//
// - `disk_description` (string) - The value of disk description is blank by
// default. \[2, 256\] characters. The disk description will appear on the
@@ -136,73 +135,68 @@ 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://`.
// 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.
// 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://`.
// 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](https://packer.io/docs/commands/build.html#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](https://packer.io/docs/commands/build.html#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.
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
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
// will allow you to create those programatically.
AlicloudImageTag hcl2template.KeyValues `mapstructure:"tag" required:"false"`
// Tags applied to the destination
// image and relevant snapshots.
AlicloudImageTags map[string]string `mapstructure:"tags" required:"false"`
AlicloudDiskDevices `mapstructure:",squash"`
}
func (c *AlicloudImageConfig) Prepare(ctx *interpolate.Context) []error {
var errs []error
errs = append(errs, c.AlicloudImageTag.CopyOn(&c.AlicloudImageTags)...)
if c.AlicloudImageName == "" {
errs = append(errs, fmt.Errorf("image_name must be specified"))
} else if len(c.AlicloudImageName) < 2 || len(c.AlicloudImageName) > 128 {
@@ -211,7 +205,7 @@ func (c *AlicloudImageConfig) Prepare(ctx *interpolate.Context) []error {
strings.HasPrefix(c.AlicloudImageName, "https://") {
errs = append(errs, fmt.Errorf("image_name can't start with 'http://' or 'https://'"))
}
reg := regexp.MustCompile(`\s+`)
reg := regexp.MustCompile("\\s+")
if reg.FindString(c.AlicloudImageName) != "" {
errs = append(errs, fmt.Errorf("image_name can't include spaces"))
}
@@ -234,5 +228,9 @@ func (c *AlicloudImageConfig) Prepare(ctx *interpolate.Context) []error {
c.AlicloudImageDestinationRegions = regions
}
return errs
if len(errs) > 0 {
return errs
}
return nil
}
+3 -3
View File
@@ -57,7 +57,7 @@ type RunConfig struct {
// The security group name. The default value
// is blank. [2, 128] English or Chinese characters, must begin with an
// uppercase/lowercase letter or Chinese character. Can contain numbers, .,
// _ or -. It cannot begin with `http://` or `https://`.
// _ or -. It cannot begin with http:// or https://.
SecurityGroupName string `mapstructure:"security_group_name" required:"false"`
// User data to apply when launching the instance. Note
// that you need to be careful about escaping characters due to the templates
@@ -73,8 +73,8 @@ type RunConfig struct {
// The VPC name. The default value is blank. [2, 128]
// English or Chinese characters, must begin with an uppercase/lowercase
// letter or Chinese character. Can contain numbers, _ and -. The disk
// description will appear on the console. Cannot begin with `http://` or
// `https://`.
// description will appear on the console. Cannot begin with http:// or
// https://.
VpcName string `mapstructure:"vpc_name" required:"false"`
// Value options: 192.168.0.0/16 and
// 172.16.0.0/16. When not specified, the default value is 172.16.0.0/16.
+45 -64
View File
@@ -18,7 +18,6 @@ import (
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/common/chroot"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
@@ -48,11 +47,11 @@ type Config struct {
// in the Chroot Mounts section. Please read that section for more
// information on how to use this.
ChrootMounts [][]string `mapstructure:"chroot_mounts" required:"false"`
// How to run shell commands. This defaults to `{{.Command}}`. This may be
// How to run shell commands. This defaults to {{.Command}}. This may be
// useful to set if you want to set environmental variables or perhaps run
// it with sudo or so on. This is a configuration template where the
// .Command variable is replaced with the command to be run. Defaults to
// `{{.Command}}`.
// {{.Command}}.
CommandWrapper string `mapstructure:"command_wrapper" required:"false"`
// Paths to files on the running EC2 instance that will be copied into the
// chroot environment prior to provisioning. Defaults to /etc/resolv.conf
@@ -90,18 +89,18 @@ type Config struct {
MountPartition string `mapstructure:"mount_partition" required:"false"`
// The path where the volume will be mounted. This is where the chroot
// environment will be. This defaults to
// `/mnt/packer-amazon-chroot-volumes/{{.Device}}`. This is a configuration
// /mnt/packer-amazon-chroot-volumes/{{.Device}}. This is a configuration
// template where the .Device variable is replaced with the name of the
// device where the volume is attached.
MountPath string `mapstructure:"mount_path" required:"false"`
// As pre_mount_commands, but the commands are executed after mounting the
// root device and before the extra mount and copy steps. The device and
// mount path are provided by `{{.Device}}` and `{{.MountPath}}`.
// mount path are provided by {{.Device}} and {{.MountPath}}.
PostMountCommands []string `mapstructure:"post_mount_commands" required:"false"`
// A series of commands to execute after attaching the root volume and
// before mounting the chroot. This is not required unless using
// from_scratch. If so, this should include any partitioning and filesystem
// creation commands. The path to the device is provided by `{{.Device}}`.
// creation commands. The path to the device is provided by {{.Device}}.
PreMountCommands []string `mapstructure:"pre_mount_commands" required:"false"`
// The root device name. For example, xvda.
RootDeviceName string `mapstructure:"root_device_name" required:"false"`
@@ -121,54 +120,50 @@ type Config struct {
SourceAmi string `mapstructure:"source_ami" required:"true"`
// Filters used to populate the source_ami field. Example:
//
//```json
//{
// "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,
//`most_recent` will cause this to succeed by selecting the newest image.
// ``` json
// {
// "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` (map of strings) - filters used to select a `source_ami`.
// NOTE: This will fail unless *exactly* one AMI is returned. Any filter
// described in the docs for
// [DescribeImages](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeImages.html)
// is valid.
// 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,
// `most_recent` will cause this to succeed by selecting the newest image.
//
//- `owners` (array of strings) - Filters the images by their owner. You
// may specify one or more AWS account IDs, "self" (which will use the
// account whose credentials you are using to run Packer), or an AWS owner
// alias: for example, "amazon", "aws-marketplace", or "microsoft". This
// option is required for security reasons.
// - `filters` (map of strings) - filters used to select a `source_ami`.
// NOTE: This will fail unless *exactly* one AMI is returned. Any filter
// described in the docs for
// [DescribeImages](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeImages.html)
// is valid.
//
//- `most_recent` (boolean) - Selects the newest created image when true.
// This is most useful for selecting a daily distro build.
// - `owners` (array of strings) - Filters the images by their owner. You
// may specify one or more AWS account IDs, "self" (which will use the
// account whose credentials you are using to run Packer), or an AWS owner
// alias: for example, "amazon", "aws-marketplace", or "microsoft". This
// option is required for security reasons.
//
//You may set this in place of `source_ami` or in conjunction with it. If you
//set this in conjunction with `source_ami`, the `source_ami` will be added
//to the filter. The provided `source_ami` must meet all of the filtering
//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.
// - `most_recent` (boolean) - Selects the newest created image when true.
// This is most useful for selecting a daily distro build.
//
// You may set this in place of `source_ami` or in conjunction with it. If you
// set this in conjunction with `source_ami`, the `source_ami` will be added
// to the filter. The provided `source_ami` must meet all of the filtering
// 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.html), 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
// [`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"`
RootVolumeTags awscommon.TagMap `mapstructure:"root_volume_tags" 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"`
@@ -259,9 +254,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
var errs *packer.MultiError
var warns []string
errs = packer.MultiErrorAppend(errs, b.config.RootVolumeTag.CopyOn(&b.config.RootVolumeTags)...)
errs = packer.MultiErrorAppend(errs, b.config.SourceAmiFilter.Prepare()...)
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)...)
@@ -335,9 +327,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
}
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
generatedData := awscommon.GetGeneratedDataList()
generatedData = append(generatedData, "Device", "MountPath")
generatedData := []string{"SourceAMIName", "Device", "MountPath"}
return generatedData, warns, nil
}
@@ -398,15 +388,12 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
GeneratedData: generatedData,
},
&StepCreateVolume{
PollingConfig: b.config.PollingConfig,
RootVolumeType: b.config.RootVolumeType,
RootVolumeSize: b.config.RootVolumeSize,
RootVolumeTags: b.config.RootVolumeTags,
Ctx: b.config.ctx,
},
&StepAttachVolume{
PollingConfig: b.config.PollingConfig,
},
&StepAttachVolume{},
&StepEarlyUnflock{},
&chroot.StepPreMountCommands{
Commands: b.config.PreMountCommands,
@@ -425,14 +412,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
&chroot.StepCopyFiles{
Files: b.config.CopyFiles,
},
&awscommon.StepSetGeneratedData{
GeneratedData: generatedData,
},
&chroot.StepChrootProvision{},
&chroot.StepEarlyCleanup{},
&StepSnapshot{
PollingConfig: b.config.PollingConfig,
},
&StepSnapshot{},
&awscommon.StepDeregisterAMI{
AccessConfig: &b.config.AccessConfig,
ForceDeregister: b.config.AMIForceDeregister,
@@ -445,7 +427,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
EnableAMIENASupport: b.config.AMIENASupport,
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
PollingConfig: b.config.PollingConfig,
},
&awscommon.StepAMIRegionCopy{
AccessConfig: &b.config.AccessConfig,
+63 -72
View File
@@ -4,75 +4,70 @@ package chroot
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/hcl2template"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
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 common.TagMap `mapstructure:"tags" required:"false" cty:"tags"`
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
SnapshotTags common.TagMap `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
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 common.TagMap `mapstructure:"root_volume_tags" required:"false" cty:"root_volume_tags"`
Architecture *string `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture"`
}
// FlatMapstructure returns a new FlatConfig.
@@ -92,7 +87,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
"ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false},
@@ -102,18 +97,16 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false},
"ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false},
"skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false},
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
"force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false},
"encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false},
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(cty.String), Required: false},
"region_kms_key_ids": &hcldec.BlockAttrsSpec{TypeName: "region_kms_key_ids", ElementType: cty.String, Required: false},
"skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false},
"snapshot_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
"snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false},
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
@@ -128,7 +121,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
"chroot_mounts": &hcldec.AttrSpec{Name: "chroot_mounts", Type: cty.List(cty.List(cty.String)), Required: false},
"command_wrapper": &hcldec.AttrSpec{Name: "command_wrapper", Type: cty.String, Required: false},
@@ -146,8 +138,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"root_volume_type": &hcldec.AttrSpec{Name: "root_volume_type", Type: cty.String, Required: false},
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
"source_ami_filter": &hcldec.BlockSpec{TypeName: "source_ami_filter", Nested: hcldec.ObjectSpec((*common.FlatAmiFilterOptions)(nil).HCL2Spec())},
"root_volume_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "root_volume_tags", ElementType: cty.String, Required: false},
"ami_architecture": &hcldec.AttrSpec{Name: "ami_architecture", Type: cty.String, Required: false},
}
return s
+2 -17
View File
@@ -227,25 +227,10 @@ func TestBuilderPrepare_ReturnGeneratedData(t *testing.T) {
if generatedData[0] != "SourceAMIName" {
t.Fatalf("Generated data should contain SourceAMIName")
}
if generatedData[1] != "BuildRegion" {
t.Fatalf("Generated data should contain BuildRegion")
}
if generatedData[2] != "SourceAMI" {
t.Fatalf("Generated data should contain SourceAMI")
}
if generatedData[3] != "SourceAMICreationDate" {
t.Fatalf("Generated data should contain SourceAMICreationDate")
}
if generatedData[4] != "SourceAMIOwner" {
t.Fatalf("Generated data should contain SourceAMIOwner")
}
if generatedData[5] != "SourceAMIOwnerName" {
t.Fatalf("Generated data should contain SourceAMIOwnerName")
}
if generatedData[6] != "Device" {
if generatedData[1] != "Device" {
t.Fatalf("Generated data should contain Device")
}
if generatedData[7] != "MountPath" {
if generatedData[2] != "MountPath" {
t.Fatalf("Generated data should contain MountPath")
}
}
+4 -5
View File
@@ -19,9 +19,8 @@ import (
// device string - The location where the volume was attached.
// attach_cleanup CleanupFunc
type StepAttachVolume struct {
PollingConfig *awscommon.AWSPollingConfig
attached bool
volumeId string
attached bool
volumeId string
}
func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@@ -52,7 +51,7 @@ func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) mu
s.volumeId = volumeId
// Wait for the volume to become attached
err = s.PollingConfig.WaitUntilVolumeAttached(ctx, ec2conn, s.volumeId)
err = awscommon.WaitUntilVolumeAttached(ctx, ec2conn, s.volumeId)
if err != nil {
err := fmt.Errorf("Error waiting for volume: %s", err)
state.Put("error", err)
@@ -88,7 +87,7 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
s.attached = false
// Wait for the volume to detach
err = s.PollingConfig.WaitUntilVolumeDetached(aws.BackgroundContext(), ec2conn, s.volumeId)
err = awscommon.WaitUntilVolumeDetached(aws.BackgroundContext(), ec2conn, s.volumeId)
if err != nil {
return fmt.Errorf("Error waiting for volume: %s", err)
}
+3 -4
View File
@@ -20,11 +20,10 @@ import (
// Produces:
// volume_id string - The ID of the created volume
type StepCreateVolume struct {
PollingConfig *awscommon.AWSPollingConfig
volumeId string
RootVolumeSize int64
RootVolumeType string
RootVolumeTags map[string]string
RootVolumeTags awscommon.TagMap
Ctx interpolate.Context
}
@@ -34,7 +33,7 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu
instance := state.Get("instance").(*ec2.Instance)
ui := state.Get("ui").(packer.Ui)
volTags, err := awscommon.TagMap(s.RootVolumeTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
volTags, err := s.RootVolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging volumes: %s", err)
state.Put("error", err)
@@ -111,7 +110,7 @@ func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) mu
log.Printf("Volume ID: %s", s.volumeId)
// Wait for the volume to become ready
err = s.PollingConfig.WaitUntilVolumeAvailable(ctx, ec2conn, s.volumeId)
err = awscommon.WaitUntilVolumeAvailable(ctx, ec2conn, s.volumeId)
if err != nil {
err := fmt.Errorf("Error waiting for volume: %s", err)
state.Put("error", err)
+1 -2
View File
@@ -15,7 +15,6 @@ import (
// StepRegisterAMI creates the AMI.
type StepRegisterAMI struct {
PollingConfig *awscommon.AWSPollingConfig
RootVolumeSize int64
EnableAMIENASupport confighelper.Trilean
EnableAMISriovNetSupport bool
@@ -82,7 +81,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul
state.Put("amis", amis)
ui.Say("Waiting for AMI to become ready...")
if err := s.PollingConfig.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
if err := awscommon.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
err := fmt.Errorf("Error waiting for AMI: %s", err)
state.Put("error", err)
ui.Error(err.Error())
+2 -3
View File
@@ -16,8 +16,7 @@ import (
// Produces:
// snapshot_id string - ID of the created snapshot
type StepSnapshot struct {
PollingConfig *awscommon.AWSPollingConfig
snapshotId string
snapshotId string
}
func (s *StepSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@@ -44,7 +43,7 @@ func (s *StepSnapshot) Run(ctx context.Context, state multistep.StateBag) multis
ui.Message(fmt.Sprintf("Snapshot ID: %s", s.snapshotId))
// Wait for the snapshot to be ready
err = s.PollingConfig.WaitUntilSnapshotDone(ctx, ec2conn, s.snapshotId)
err = awscommon.WaitUntilSnapshotDone(ctx, ec2conn, s.snapshotId)
if err != nil {
err := fmt.Errorf("Error waiting for snapshot: %s", err)
state.Put("error", err)
+7 -26
View File
@@ -44,7 +44,7 @@ func (v *VaultAWSEngineOptions) Empty() bool {
// AccessConfig is for common configuration related to AWS access
type AccessConfig struct {
// The access key used to communicate with AWS. [Learn how to set this]
// (/docs/builders/amazon#specifying-amazon-credentials). On EBS, this
// (/docs/builders/amazon.html#specifying-amazon-credentials). On EBS, this
// is not required if you are using `use_vault_aws_engine` for
// authentication instead.
AccessKey string `mapstructure:"access_key" required:"true"`
@@ -79,7 +79,7 @@ type AccessConfig struct {
// When chroot building, this value is guessed from environment.
RawRegion string `mapstructure:"region" required:"true"`
// The secret key used to communicate with AWS. [Learn how to set
// this](/docs/builders/amazon#specifying-amazon-credentials). This is not required
// this](amazon.html#specifying-amazon-credentials). This is not required
// if you are using `use_vault_aws_engine` for authentication instead.
SecretKey string `mapstructure:"secret_key" required:"true"`
// Set to true if you want to skip
@@ -95,7 +95,7 @@ type AccessConfig struct {
// Get credentials from Hashicorp Vault's aws secrets engine. You must
// already have created a role to use. For more information about
// generating credentials via the Vault engine, see the [Vault
// docs.](https://www.vaultproject.io/api/secret/aws#generate-credentials)
// docs.](https://www.vaultproject.io/api/secret/aws/index.html#generate-credentials)
// If you set this flag, you must also set the below options:
// - `name` (string) - Required. Specifies the name of the role to generate
// credentials against. This is part of the request URL.
@@ -116,9 +116,7 @@ type AccessConfig struct {
// credential types) and GetFederationToken (for federation\_token
// credential types) for more details.
//
// JSON example:
//
// ```json
// ``` json
// {
// "vault_aws_engine": {
// "name": "myrole",
@@ -127,20 +125,7 @@ type AccessConfig struct {
// }
// }
// ```
//
// HCL2 example:
//
// ```hcl
// vault_aws_engine {
// name = "myrole"
// role_arn = "myarn"
// ttl = "3600s"
// }
// ```
VaultAWSEngine VaultAWSEngineOptions `mapstructure:"vault_aws_engine" required:"false"`
// [Polling configuration](#polling-configuration) for the AWS waiter. Configures the waiter that checks
// resource state.
PollingConfig *AWSPollingConfig `mapstructure:"aws_polling" required:"false"`
getEC2Connection func() ec2iface.EC2API
}
@@ -203,9 +188,9 @@ 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 " +
"Please see https://www.packer.io/docs/builders/amazon.html#specifying-amazon-credentials " +
"for more information on providing credentials for the AWS Builder.")
}
@@ -218,6 +203,7 @@ func (c *AccessConfig) Session() (*session.Session, error) {
if c.DecodeAuthZMessages {
DecodeAuthZMessages(c.session)
}
LogEnvOverrideWarnings()
return c.session, nil
}
@@ -298,11 +284,6 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
fmt.Errorf("`access_key` and `secret_key` must both be either set or not set."))
}
if c.PollingConfig == nil {
c.PollingConfig = new(AWSPollingConfig)
}
c.PollingConfig.LogEnvOverrideWarnings()
return errs
}
@@ -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.
@@ -13,7 +13,6 @@ func testAccessConfig() *AccessConfig {
getEC2Connection: func() ec2iface.EC2API {
return &mockEC2Client{}
},
PollingConfig: new(AWSPollingConfig),
}
}
+18 -46
View File
@@ -7,7 +7,6 @@ import (
"log"
"regexp"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/template/interpolate"
)
@@ -17,11 +16,11 @@ type AMIConfig struct {
// The name of the resulting AMI that will appear when managing AMIs in the
// AWS console or via APIs. This must be unique. To help make this unique,
// use a function like timestamp (see [template
// engine](/docs/templates/engine) for more info).
// engine](../templates/engine.html) for more info).
AMIName string `mapstructure:"ami_name" required:"true"`
// The description to set for the resulting
// AMI(s). By default this description is empty. This is a
// [template engine](/docs/templates/engine), see [Build template
// [template engine](/docs/templates/engine.html), see [Build template
// data](#build-template-data) for more information.
AMIDescription string `mapstructure:"ami_description" required:"false"`
// The type of virtualization for the AMI
@@ -47,15 +46,10 @@ 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.html), 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
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
// will allow you to create those programatically.
AMITag hcl2template.KeyValues `mapstructure:"tag" required:"false"`
AMITags TagMap `mapstructure:"tags" required:"false"`
// Enable enhanced networking (ENA but not SriovNetSupport) on
// HVM-compatible AMIs. If set, add `ec2:ModifyInstanceAttribute` to your
// AWS IAM policy.
@@ -79,32 +73,18 @@ type AMIConfig struct {
// Default false.
AMIForceDeleteSnapshot bool `mapstructure:"force_delete_snapshot" required:"false"`
// Whether or not to encrypt the resulting AMI when
// copying a provisioned instance to an AMI. By default, Packer will keep
// the encryption setting to what it was in the source image. Setting false
// will result in an unencrypted image, and true will result in an encrypted
// one.
//
// copying a provisioned instance to an AMI. By default, Packer will keep the
// encryption setting to what it was in the source image. Setting false will
// result in an unencrypted image, and true will result in an encrypted one.
// If you have used the `launch_block_device_mappings` to set an encryption
// key and that key is the same as the one you want the image encrypted with
// at the end, then you don't need to set this field; leaving it empty will
// prevent an unnecessary extra copy step and save you some time.
AMIEncryptBootVolume config.Trilean `mapstructure:"encrypt_boot" required:"false"`
// ID, alias or ARN of the KMS key to use for AMI encryption. This
// only applies to the main `region` -- any regions the AMI gets copied to
// copied will be encrypted by the default EBS KMS key for that region,
// unless you set region-specific keys in AMIRegionKMSKeyIDs.
//
// Set this value if you select `encrypt_boot`, but don't want to use the
// region's default KMS key.
//
// If you have a custom kms key you'd like to apply to the launch volume,
// and are only building in one region, it is more efficient to leave this
// and `encrypt_boot` empty and to instead set the key id in the
// launch_block_device_mappings (you can find an example below). This saves
// potentially many minutes at the end of the build by preventing Packer
// from having to copy and re-encrypt the image at the end of the build.
//
// For valid formats see *KmsKeyId* in the [AWS API docs -
// ID, alias or ARN of the KMS key to use for boot volume encryption. This
// only applies to the main `region`, other regions where the AMI will be
// copied will be encrypted by the default EBS KMS key. For valid formats
// see *KmsKeyId* in the [AWS API docs -
// CopyImage](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CopyImage.html).
// This field is validated by Packer, when using an alias, you will have to
// prefix `kms_key_id` with `alias/`.
@@ -131,16 +111,11 @@ 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](../templates/engine.html), 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
// [`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"`
SnapshotTags TagMap `mapstructure:"snapshot_tags" 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
@@ -165,9 +140,6 @@ func stringInSlice(s []string, searchstr string) bool {
func (c *AMIConfig) Prepare(accessConfig *AccessConfig, ctx *interpolate.Context) []error {
var errs []error
errs = append(errs, c.SnapshotTag.CopyOn(&c.SnapshotTags)...)
errs = append(errs, c.AMITag.CopyOn(&c.AMITags)...)
if c.AMIName == "" {
errs = append(errs, fmt.Errorf("ami_name must be specified"))
}
@@ -217,14 +189,14 @@ func (c *AMIConfig) Prepare(accessConfig *AccessConfig, ctx *interpolate.Context
}
for _, kmsKey := range kmsKeys {
if !validateKmsKey(kmsKey) {
errs = append(errs, fmt.Errorf("%q is not a valid KMS Key Id.", kmsKey))
errs = append(errs, fmt.Errorf("%s is not a valid KMS Key Id.", kmsKey))
}
}
if len(c.SnapshotUsers) > 0 {
if len(c.AMIKmsKeyId) == 0 && len(c.AMIRegionKMSKeyIDs) == 0 && c.AMIEncryptBootVolume.True() {
errs = append(errs, fmt.Errorf("Cannot share snapshot encrypted "+
"with default KMS key, see https://www.packer.io/docs/builders/amazon-ebs#region_kms_key_ids for more information"))
"with default KMS key, see https://www.packer.io/docs/builders/amazon-ebs.html#region_kms_key_ids for more information"))
}
if len(c.AMIRegionKMSKeyIDs) > 0 {
for _, kmsKey := range c.AMIRegionKMSKeyIDs {
+12 -31
View File
@@ -13,7 +13,7 @@ import (
"github.com/hashicorp/packer/template/interpolate"
)
// These will be attached when launching your instance. Your
// These will be attached when booting a new instance from your AMI. Your
// options here may vary depending on the type of VM you use.
//
// Example use case:
@@ -21,31 +21,14 @@ 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
// launch_block_device_mappings: [
// {
// "device_name": "/dev/sda1",
// "encrypted": true,
// "kms_key_id": "1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d"
// }
// ]
// ``` json
// "[{
// "device_name": "/dev/sda1",
// "encrypted": true,
// "kms_key_id": "1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d"
// }]
// ```
//
// HCL2 example:
//
// ```hcl
// launch_block_device_mappings {
// device_name = "/dev/sda1"
// encrypted = true
// kms_key_id = "1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d"
// }
// ```
//
// Please note that the kms_key_id option in this example exists for
// launch_block_device_mappings but not ami_block_device_mappings.
//
// Documentation for Block Devices Mappings can be found here:
// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html
//
@@ -83,14 +66,12 @@ type BlockDevice struct {
// The size of the volume, in GiB. Required if not specifying a
// snapshot_id.
VolumeSize int64 `mapstructure:"volume_size" required:"false"`
// ID, alias or ARN of the KMS key to use for boot volume encryption.
// This option exists for launch_block_device_mappings but not
// ami_block_device_mappings. The kms key id defined here only applies to
// the original build region; if the AMI gets copied to other regions, the
// volume in those regions will be encrypted by the default EBS KMS key.
// For valid formats see KmsKeyId in the [AWS API docs -
// ID, alias or ARN of the KMS key to use for boot volume encryption. This
// only applies to the main region, other regions where the AMI will be
// copied will be encrypted by the default EBS KMS key. For valid formats
// see KmsKeyId in the [AWS API docs -
// CopyImage](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CopyImage.html)
// This field is validated by Packer. When using an alias, you will have to
// This field is validated by Packer, when using an alias, you will have to
// prefix kms_key_id with alias/.
KmsKeyId string `mapstructure:"kms_key_id" required:"false"`
}
+10 -10
View File
@@ -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.
+3 -3
View File
@@ -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)
}
+12 -32
View File
@@ -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,32 +31,13 @@ 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("BuildRegion", buildInfoTemplate.BuildRegion)
generatedData.Put("SourceAMI", buildInfoTemplate.SourceAMI)
generatedData.Put("SourceAMICreationDate", buildInfoTemplate.SourceAMICreationDate)
generatedData.Put("SourceAMIName", buildInfoTemplate.SourceAMIName)
generatedData.Put("SourceAMIOwner", buildInfoTemplate.SourceAMIOwner)
generatedData.Put("SourceAMIOwnerName", buildInfoTemplate.SourceAMIOwnerName)
return buildInfoTemplate
}
func GetGeneratedDataList() []string {
return []string{
"SourceAMIName",
"BuildRegion",
"SourceAMI",
"SourceAMICreationDate",
"SourceAMIOwner",
"SourceAMIOwnerName",
}
}
@@ -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",
+62 -172
View File
@@ -12,7 +12,6 @@ import (
"time"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/template/interpolate"
)
@@ -20,9 +19,9 @@ import (
var reShutdownBehavior = regexp.MustCompile("^(stop|terminate)$")
type AmiFilterOptions struct {
hcl2template.KeyValueFilter `mapstructure:",squash"`
Owners []string
MostRecent bool `mapstructure:"most_recent"`
Filters map[string]string
Owners []string
MostRecent bool `mapstructure:"most_recent"`
}
func (d *AmiFilterOptions) GetOwners() []*string {
@@ -35,7 +34,7 @@ func (d *AmiFilterOptions) GetOwners() []*string {
}
func (d *AmiFilterOptions) Empty() bool {
return len(d.Owners) == 0 && d.KeyValueFilter.Empty()
return len(d.Owners) == 0 && len(d.Filters) == 0
}
func (d *AmiFilterOptions) NoOwner() bool {
@@ -43,19 +42,23 @@ func (d *AmiFilterOptions) NoOwner() bool {
}
type SubnetFilterOptions struct {
hcl2template.NameValueFilter `mapstructure:",squash"`
MostFree bool `mapstructure:"most_free"`
Random bool `mapstructure:"random"`
Filters map[string]string
MostFree bool `mapstructure:"most_free"`
Random bool `mapstructure:"random"`
}
func (d *SubnetFilterOptions) Empty() bool {
return len(d.Filters) == 0
}
type VpcFilterOptions struct {
hcl2template.NameValueFilter `mapstructure:",squash"`
Filters map[string]string
}
type Statement struct {
Effect string
Action []string
Resource []string
Resource string
}
type PolicyDocument struct {
@@ -63,8 +66,16 @@ type PolicyDocument struct {
Statement []Statement
}
func (d *VpcFilterOptions) Empty() bool {
return len(d.Filters) == 0
}
type SecurityGroupFilterOptions struct {
hcl2template.NameValueFilter `mapstructure:",squash"`
Filters map[string]string
}
func (d *SecurityGroupFilterOptions) Empty() bool {
return len(d.Filters) == 0
}
// RunConfig contains configuration for running an instance from a source
@@ -89,23 +100,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](https://www.packer.io/docs/provisioners/windows-shell.html).
// 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,9 +173,9 @@ 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
// ``` json
// {
// "security_group_filter": {
// "filters": {
@@ -178,16 +185,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 +194,10 @@ 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.html),
// 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
// [`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"`
// 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 +214,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 +286,15 @@ 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
// spot request that is issued.
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
// [`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"`
// 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 +303,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 +348,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 = {
// ``` json
// {
// "vpc_filter": {
// "filters": {
// "tag:Class": "build",
// "isDefault": "false",
// "cidr": "/24"
@@ -451,8 +387,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 +398,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 {
@@ -501,42 +423,15 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
// Validation
errs := c.Comm.Prepare(ctx)
// Copy singular tag maps
errs = append(errs, c.RunTag.CopyOn(&c.RunTags)...)
errs = append(errs, c.SpotTag.CopyOn(&c.SpotTags)...)
for _, preparer := range []interface{ Prepare() []error }{
&c.SourceAmiFilter,
&c.SecurityGroupFilter,
&c.SubnetFilter,
&c.VpcFilter,
} {
errs = append(errs, preparer.Prepare()...)
}
// Validating ssh_interface
if c.SSHInterface != "public_ip" &&
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 +505,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 +521,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
}
+18 -27
View File
@@ -3,17 +3,15 @@ package common
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/hcl2template"
"github.com/zclconf/go-cty/cty"
)
// 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"`
Owners []string `cty:"owners"`
MostRecent *bool `mapstructure:"most_recent" cty:"most_recent"`
}
// FlatMapstructure returns a new FlatAmiFilterOptions.
@@ -28,8 +26,7 @@ func (*AmiFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcl
// The decoded values from this spec will then be applied to a FlatAmiFilterOptions.
func (*FlatAmiFilterOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
"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 +36,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 +61,7 @@ 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"`
}
// FlatMapstructure returns a new FlatSecurityGroupFilterOptions.
@@ -80,8 +76,7 @@ func (*SecurityGroupFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[
// The decoded values from this spec will then be applied to a FlatSecurityGroupFilterOptions.
func (*FlatSecurityGroupFilterOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
}
return s
}
@@ -89,9 +84,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 +103,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 +111,9 @@ 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"`
MostFree *bool `mapstructure:"most_free" cty:"most_free"`
Random *bool `mapstructure:"random" cty:"random"`
}
// FlatMapstructure returns a new FlatSubnetFilterOptions.
@@ -134,8 +128,7 @@ func (*SubnetFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]
// The decoded values from this spec will then be applied to a FlatSubnetFilterOptions.
func (*FlatSubnetFilterOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
"most_free": &hcldec.AttrSpec{Name: "most_free", Type: cty.Bool, Required: false},
"random": &hcldec.AttrSpec{Name: "random", Type: cty.Bool, Required: false},
}
@@ -145,8 +138,7 @@ 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"`
}
// FlatMapstructure returns a new FlatVpcFilterOptions.
@@ -161,8 +153,7 @@ func (*VpcFilterOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcl
// The decoded values from this spec will then be applied to a FlatVpcFilterOptions.
func (*FlatVpcFilterOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"filters": &hcldec.AttrSpec{Name: "filters", Type: cty.Map(cty.String), Required: false},
"filter": &hcldec.BlockListSpec{TypeName: "filter", Nested: hcldec.ObjectSpec((*hcl2template.FlatNameValue)(nil).HCL2Spec())},
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
}
return s
}
+2 -8
View File
@@ -6,7 +6,6 @@ import (
"regexp"
"testing"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/helper/communicator"
)
@@ -74,7 +73,7 @@ func TestRunConfigPrepare_SourceAmiFilterOwnersBlank(t *testing.T) {
c := testConfigFilter()
filter_key := "name"
filter_value := "foo"
c.SourceAmiFilter.Filters = map[string]string{filter_key: filter_value}
c.SourceAmiFilter = AmiFilterOptions{Filters: map[string]string{filter_key: filter_value}}
if err := c.Prepare(nil); len(err) != 1 {
t.Fatalf("Should error if Owners is not specified)")
}
@@ -85,12 +84,7 @@ func TestRunConfigPrepare_SourceAmiFilterGood(t *testing.T) {
owner := "123"
filter_key := "name"
filter_value := "foo"
goodFilter := AmiFilterOptions{
Owners: []string{owner},
KeyValueFilter: hcl2template.KeyValueFilter{
Filters: map[string]string{filter_key: filter_value},
},
}
goodFilter := AmiFilterOptions{Owners: []string{owner}, Filters: map[string]string{filter_key: filter_value}}
c.SourceAmiFilter = goodFilter
if err := c.Prepare(nil); len(err) != 0 {
t.Fatalf("err: %s", err)
-21
View File
@@ -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
}
}
-3
View File
@@ -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, ""},
-182
View File
@@ -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
}
-188
View File
@@ -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)
}
})
}
}
-56
View File
@@ -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
}
+33 -82
View File
@@ -1,5 +1,3 @@
//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type AWSPollingConfig
package common
import (
@@ -40,45 +38,12 @@ type StateChangeConf struct {
// Following are wrapper functions that use Packer's environment-variables to
// determine retry logic, then call the AWS SDK's built-in waiters.
// Polling configuration for the AWS waiter. Configures the waiter for resources creation or actions like attaching
// volumes or importing image.
// Usage example:
//
// In JSON:
// ```json
// "aws_polling" : {
// "delay_seconds": 30,
// "max_attempts": 50
// }
// ```
//
// In HCL2:
// ```hcl
// aws_polling {
// delay_seconds = 30
// max_attempts = 50
// }
// ```
//
type AWSPollingConfig struct {
// Specifies the maximum number of attempts the waiter will check for resource state.
// This value can also be set via the AWS_MAX_ATTEMPTS.
// If both option and environment variable are set, the max_attempts will be considered over the AWS_MAX_ATTEMPTS.
// If none is set, defaults to AWS waiter default which is 40 max_attempts.
MaxAttempts int `mapstructure:"max_attempts" required:"false"`
// Specifies the delay in seconds between attempts to check the resource state.
// This value can also be set via the AWS_POLL_DELAY_SECONDS.
// If both option and environment variable are set, the delay_seconds will be considered over the AWS_POLL_DELAY_SECONDS.
// If none is set, defaults to AWS waiter default which is 15 seconds.
DelaySeconds int `mapstructure:"delay_seconds" required:"false"`
}
func (w *AWSPollingConfig) WaitUntilAMIAvailable(ctx aws.Context, conn ec2iface.EC2API, imageId string) error {
func WaitUntilAMIAvailable(ctx aws.Context, conn ec2iface.EC2API, imageId string) error {
imageInput := ec2.DescribeImagesInput{
ImageIds: []*string{&imageId},
}
waitOpts := w.getWaiterOptions()
waitOpts := getWaiterOptions()
if len(waitOpts) == 0 {
// Bump this default to 30 minutes because the aws default
// of ten minutes doesn't work for some of our long-running copies.
@@ -101,7 +66,7 @@ func (w *AWSPollingConfig) WaitUntilAMIAvailable(ctx aws.Context, conn ec2iface.
return err
}
func (w *AWSPollingConfig) WaitUntilInstanceRunning(ctx aws.Context, conn *ec2.EC2, instanceId string) error {
func WaitUntilInstanceRunning(ctx aws.Context, conn *ec2.EC2, instanceId string) error {
instanceInput := ec2.DescribeInstancesInput{
InstanceIds: []*string{&instanceId},
@@ -110,11 +75,12 @@ func (w *AWSPollingConfig) WaitUntilInstanceRunning(ctx aws.Context, conn *ec2.E
err := conn.WaitUntilInstanceRunningWithContext(
ctx,
&instanceInput,
w.getWaiterOptions()...)
getWaiterOptions()...)
return err
}
func (w *AWSPollingConfig) WaitUntilInstanceTerminated(ctx aws.Context, conn *ec2.EC2, instanceId string) error {
func WaitUntilInstanceTerminated(ctx aws.Context, conn *ec2.EC2, instanceId string) error {
instanceInput := ec2.DescribeInstancesInput{
InstanceIds: []*string{&instanceId},
}
@@ -122,12 +88,12 @@ func (w *AWSPollingConfig) WaitUntilInstanceTerminated(ctx aws.Context, conn *ec
err := conn.WaitUntilInstanceTerminatedWithContext(
ctx,
&instanceInput,
w.getWaiterOptions()...)
getWaiterOptions()...)
return err
}
// This function works for both requesting and cancelling spot instances.
func (w *AWSPollingConfig) WaitUntilSpotRequestFulfilled(ctx aws.Context, conn *ec2.EC2, spotRequestId string) error {
func WaitUntilSpotRequestFulfilled(ctx aws.Context, conn *ec2.EC2, spotRequestId string) error {
spotRequestInput := ec2.DescribeSpotInstanceRequestsInput{
SpotInstanceRequestIds: []*string{&spotRequestId},
}
@@ -135,11 +101,11 @@ func (w *AWSPollingConfig) WaitUntilSpotRequestFulfilled(ctx aws.Context, conn *
err := conn.WaitUntilSpotInstanceRequestFulfilledWithContext(
ctx,
&spotRequestInput,
w.getWaiterOptions()...)
getWaiterOptions()...)
return err
}
func (w *AWSPollingConfig) WaitUntilVolumeAvailable(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
func WaitUntilVolumeAvailable(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
volumeInput := ec2.DescribeVolumesInput{
VolumeIds: []*string{&volumeId},
}
@@ -147,11 +113,11 @@ func (w *AWSPollingConfig) WaitUntilVolumeAvailable(ctx aws.Context, conn *ec2.E
err := conn.WaitUntilVolumeAvailableWithContext(
ctx,
&volumeInput,
w.getWaiterOptions()...)
getWaiterOptions()...)
return err
}
func (w *AWSPollingConfig) WaitUntilSnapshotDone(ctx aws.Context, conn *ec2.EC2, snapshotID string) error {
func WaitUntilSnapshotDone(ctx aws.Context, conn *ec2.EC2, snapshotID string) error {
snapInput := ec2.DescribeSnapshotsInput{
SnapshotIds: []*string{&snapshotID},
}
@@ -159,13 +125,13 @@ func (w *AWSPollingConfig) WaitUntilSnapshotDone(ctx aws.Context, conn *ec2.EC2,
err := conn.WaitUntilSnapshotCompletedWithContext(
ctx,
&snapInput,
w.getWaiterOptions()...)
getWaiterOptions()...)
return err
}
// Wrappers for our custom AWS waiters
func (w *AWSPollingConfig) WaitUntilVolumeAttached(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
func WaitUntilVolumeAttached(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
volumeInput := ec2.DescribeVolumesInput{
VolumeIds: []*string{&volumeId},
}
@@ -173,11 +139,11 @@ func (w *AWSPollingConfig) WaitUntilVolumeAttached(ctx aws.Context, conn *ec2.EC
err := WaitForVolumeToBeAttached(conn,
ctx,
&volumeInput,
w.getWaiterOptions()...)
getWaiterOptions()...)
return err
}
func (w *AWSPollingConfig) WaitUntilVolumeDetached(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
func WaitUntilVolumeDetached(ctx aws.Context, conn *ec2.EC2, volumeId string) error {
volumeInput := ec2.DescribeVolumesInput{
VolumeIds: []*string{&volumeId},
}
@@ -185,11 +151,11 @@ func (w *AWSPollingConfig) WaitUntilVolumeDetached(ctx aws.Context, conn *ec2.EC
err := WaitForVolumeToBeDetached(conn,
ctx,
&volumeInput,
w.getWaiterOptions()...)
getWaiterOptions()...)
return err
}
func (w *AWSPollingConfig) WaitUntilImageImported(ctx aws.Context, conn *ec2.EC2, taskID string) error {
func WaitUntilImageImported(ctx aws.Context, conn *ec2.EC2, taskID string) error {
importInput := ec2.DescribeImportImageTasksInput{
ImportTaskIds: []*string{&taskID},
}
@@ -197,7 +163,7 @@ func (w *AWSPollingConfig) WaitUntilImageImported(ctx aws.Context, conn *ec2.EC2
err := WaitForImageToBeImported(conn,
ctx,
&importInput,
w.getWaiterOptions()...)
getWaiterOptions()...)
return err
}
@@ -332,18 +298,8 @@ type overridableWaitVars struct {
awsTimeoutSeconds envInfo
}
func (w *AWSPollingConfig) getWaiterOptions() []request.WaiterOption {
func getWaiterOptions() []request.WaiterOption {
envOverrides := getEnvOverrides()
if w.MaxAttempts != 0 {
envOverrides.awsMaxAttempts.Val = w.MaxAttempts
envOverrides.awsMaxAttempts.overridden = true
}
if w.DelaySeconds != 0 {
envOverrides.awsPollDelaySeconds.Val = w.DelaySeconds
envOverrides.awsPollDelaySeconds.overridden = true
}
waitOpts := applyEnvOverrides(envOverrides)
return waitOpts
}
@@ -377,38 +333,33 @@ func getEnvOverrides() overridableWaitVars {
return envValues
}
func (w *AWSPollingConfig) LogEnvOverrideWarnings() {
pollDelayEnv := os.Getenv("AWS_POLL_DELAY_SECONDS")
timeoutSecondsEnv := os.Getenv("AWS_TIMEOUT_SECONDS")
maxAttemptsEnv := os.Getenv("AWS_MAX_ATTEMPTS")
func LogEnvOverrideWarnings() {
pollDelay := os.Getenv("AWS_POLL_DELAY_SECONDS")
timeoutSeconds := os.Getenv("AWS_TIMEOUT_SECONDS")
maxAttempts := os.Getenv("AWS_MAX_ATTEMPTS")
maxAttemptsIsSet := maxAttemptsEnv != "" || w.MaxAttempts != 0
timeoutSecondsIsSet := timeoutSecondsEnv != ""
pollDelayIsSet := pollDelayEnv != "" || w.DelaySeconds != 0
if maxAttemptsIsSet && timeoutSecondsIsSet {
if maxAttempts != "" && timeoutSeconds != "" {
warning := fmt.Sprintf("[WARNING] (aws): AWS_MAX_ATTEMPTS and " +
"AWS_TIMEOUT_SECONDS are both set. Packer will use " +
"AWS_MAX_ATTEMPTS and discard AWS_TIMEOUT_SECONDS.")
if !pollDelayIsSet {
if pollDelay == "" {
warning = fmt.Sprintf("%s Since you have not set the poll delay, "+
"Packer will default to a 2-second delay.", warning)
}
log.Printf(warning)
} else if timeoutSecondsIsSet {
} else if timeoutSeconds != "" {
log.Printf("[WARNING] (aws): env var AWS_TIMEOUT_SECONDS is " +
"deprecated in favor of AWS_MAX_ATTEMPTS env or aws_polling_max_attempts config option. " +
"If you have not explicitly set AWS_POLL_DELAY_SECONDS env or aws_polling_delay_seconds config option, " +
"we are defaulting to a poll delay of 2 seconds, regardless of the AWS waiter's default.")
"deprecated in favor of AWS_MAX_ATTEMPTS. If you have not " +
"explicitly set AWS_POLL_DELAY_SECONDS, we are defaulting to a " +
"poll delay of 2 seconds, regardless of the AWS waiter's default.")
}
if !maxAttemptsIsSet && !timeoutSecondsIsSet && !pollDelayIsSet {
if maxAttempts == "" && timeoutSeconds == "" && pollDelay == "" {
log.Printf("[INFO] (aws): No AWS timeout and polling overrides have been set. " +
"Packer will default to waiter-specific delays and timeouts. If you would " +
"like to customize the length of time between retries and max " +
"number of retries you may do so by setting the environment " +
"variables AWS_POLL_DELAY_SECONDS and AWS_MAX_ATTEMPTS or the " +
"configuration options aws_polling_delay_seconds and aws_polling_max_attempts " +
"to your desired values.")
"variables AWS_POLL_DELAY_SECONDS and AWS_MAX_ATTEMPTS to your " +
"desired values.")
}
}
-32
View File
@@ -1,32 +0,0 @@
// Code generated by "mapstructure-to-hcl2 -type AWSPollingConfig"; DO NOT EDIT.
package common
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// FlatAWSPollingConfig is an auto-generated flat version of AWSPollingConfig.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatAWSPollingConfig struct {
MaxAttempts *int `mapstructure:"max_attempts" required:"false" cty:"max_attempts" hcl:"max_attempts"`
DelaySeconds *int `mapstructure:"delay_seconds" required:"false" cty:"delay_seconds" hcl:"delay_seconds"`
}
// FlatMapstructure returns a new FlatAWSPollingConfig.
// FlatAWSPollingConfig is an auto-generated flat version of AWSPollingConfig.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*AWSPollingConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatAWSPollingConfig)
}
// HCL2Spec returns the hcl spec of a AWSPollingConfig.
// This spec is used by HCL to read the fields of AWSPollingConfig.
// The decoded values from this spec will then be applied to a FlatAWSPollingConfig.
func (*FlatAWSPollingConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"max_attempts": &hcldec.AttrSpec{Name: "max_attempts", Type: cty.Number, Required: false},
"delay_seconds": &hcldec.AttrSpec{Name: "delay_seconds", Type: cty.Number, Required: false},
}
return s
}
@@ -209,7 +209,7 @@ func (s *StepAMIRegionCopy) amiRegionCopy(ctx context.Context, state multistep.S
}
// Wait for the image to become ready
if err := s.AccessConfig.PollingConfig.WaitUntilAMIAvailable(ctx, regionconn, *resp.ImageId); err != nil {
if err := WaitUntilAMIAvailable(ctx, regionconn, *resp.ImageId); err != nil {
return "", snapshotIds, fmt.Errorf("Error waiting for AMI (%s) in region (%s): %s",
*resp.ImageId, target, err)
}
@@ -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")
}
})
}
}
+6 -6
View File
@@ -15,8 +15,8 @@ import (
)
type StepCreateTags struct {
Tags map[string]string
SnapshotTags map[string]string
Tags TagMap
SnapshotTags TagMap
Ctx interpolate.Context
}
@@ -26,7 +26,7 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult
ui := state.Get("ui").(packer.Ui)
amis := state.Get("amis").(map[string]string)
if len(s.Tags) == 0 && len(s.SnapshotTags) == 0 {
if !s.Tags.IsSet() && !s.SnapshotTags.IsSet() {
return multistep.ActionContinue
}
@@ -72,7 +72,7 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult
// Convert tags to ec2.Tag format
ui.Say("Creating AMI tags")
amiTags, err := TagMap(s.Tags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
amiTags, err := s.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
@@ -81,7 +81,7 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult
amiTags.Report(ui)
ui.Say("Creating snapshot tags")
snapshotTags, err := TagMap(s.SnapshotTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
snapshotTags, err := s.SnapshotTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
@@ -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
+2 -2
View File
@@ -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)
}
@@ -19,7 +19,6 @@ import (
)
type StepRunSourceInstance struct {
PollingConfig *AWSPollingConfig
AssociatePublicIpAddress bool
LaunchMappings EC2BlockDeviceMappingsBuilder
Comm *communicator.Config
@@ -32,10 +31,10 @@ type StepRunSourceInstance struct {
InstanceType string
IsRestricted bool
SourceAMI string
Tags map[string]string
Tags TagMap
UserData string
UserDataFile string
VolumeTags map[string]string
VolumeTags TagMap
NoEphemeral bool
instanceId string
@@ -89,7 +88,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
s.Tags["Name"] = "Packer Builder"
}
ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
ec2Tags, err := s.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging source instance: %s", err)
state.Put("error", err)
@@ -97,7 +96,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
return multistep.ActionHalt
}
volTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
volTags, err := s.VolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging volumes: %s", err)
state.Put("error", err)
@@ -199,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
@@ -210,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())
@@ -235,7 +234,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
InstanceIds: []*string{aws.String(instanceId)},
}
if err := s.PollingConfig.WaitUntilInstanceRunning(ctx, ec2conn, instanceId); err != nil {
if err := WaitUntilInstanceRunning(ctx, ec2conn, instanceId); err != nil {
err := fmt.Errorf("Error waiting for instance (%s) to become ready: %s", instanceId, err)
state.Put("error", err)
ui.Error(err.Error())
@@ -248,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
@@ -293,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
@@ -323,10 +322,10 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
}
}
if len(volumeIds) > 0 && len(s.VolumeTags) > 0 {
if len(volumeIds) > 0 && s.VolumeTags.IsSet() {
ui.Say("Adding tags to source EBS Volumes")
volumeTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
volumeTags, err := s.VolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging source EBS Volumes on %s: %s", *instance.InstanceId, err)
state.Put("error", err)
@@ -365,7 +364,7 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
return
}
if err := s.PollingConfig.WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil {
if err := WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil {
ui.Error(err.Error())
}
}
+29 -35
View File
@@ -23,7 +23,6 @@ type EC2BlockDeviceMappingsBuilder interface {
}
type StepRunSpotInstance struct {
PollingConfig *AWSPollingConfig
AssociatePublicIpAddress bool
LaunchMappings EC2BlockDeviceMappingsBuilder
BlockDurationMinutes int64
@@ -35,10 +34,10 @@ type StepRunSpotInstance struct {
InstanceType string
SourceAMI string
SpotPrice string
SpotTags map[string]string
SpotTags TagMap
SpotInstanceTypes []string
Tags map[string]string
VolumeTags map[string]string
Tags TagMap
VolumeTags TagMap
UserData string
UserDataFile string
Ctx interpolate.Context
@@ -50,6 +49,24 @@ type StepRunSpotInstance struct {
func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string,
state multistep.StateBag, marketOptions *ec2.LaunchTemplateInstanceMarketOptionsRequest) *ec2.RequestLaunchTemplateData {
blockDeviceMappings := s.LaunchMappings.BuildEC2BlockDeviceMappings()
if s.NoEphemeral {
// This is only relevant for windows guests. Ephemeral drives by
// default are assigned to drive names xvdca-xvdcz.
// When vms are launched from the AWS console, they're automatically
// removed from the block devices if the user hasn't said to use them,
// but the SDK does not perform this cleanup. The following code just
// manually removes the ephemeral drives from the mapping so that they
// don't clutter up console views and cause confusion.
log.Printf("no_ephemeral was set, so creating drives xvdca-xvdcz as empty mappings")
DefaultEphemeralDeviceLetters := "abcdefghijklmnopqrstuvwxyz"
for _, letter := range DefaultEphemeralDeviceLetters {
bd := &ec2.BlockDeviceMapping{
DeviceName: aws.String("xvdc" + string(letter)),
NoDevice: aws.String(""),
}
blockDeviceMappings = append(blockDeviceMappings, bd)
}
}
// Convert the BlockDeviceMapping into a
// LaunchTemplateBlockDeviceMappingRequest. These structs are identical,
// except for the EBS field -- on one, that field contains a
@@ -63,29 +80,11 @@ func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string,
launchRequest := &ec2.LaunchTemplateBlockDeviceMappingRequest{
DeviceName: mapping.DeviceName,
Ebs: (*ec2.LaunchTemplateEbsBlockDeviceRequest)(mapping.Ebs),
NoDevice: mapping.NoDevice,
VirtualName: mapping.VirtualName,
}
launchMappingRequests = append(launchMappingRequests, launchRequest)
}
if s.NoEphemeral {
// This is only relevant for windows guests. Ephemeral drives by
// default are assigned to drive names xvdca-xvdcz.
// When vms are launched from the AWS console, they're automatically
// removed from the block devices if the user hasn't said to use them,
// but the SDK does not perform this cleanup. The following code just
// manually removes the ephemeral drives from the mapping so that they
// don't clutter up console views and cause confusion.
log.Printf("no_ephemeral was set, so creating drives xvdca-xvdcz as empty mappings")
DefaultEphemeralDeviceLetters := "abcdefghijklmnopqrstuvwxyz"
for _, letter := range DefaultEphemeralDeviceLetters {
launchRequest := &ec2.LaunchTemplateBlockDeviceMappingRequest{
DeviceName: aws.String("xvdc" + string(letter)),
NoDevice: aws.String(""),
}
launchMappingRequests = append(launchMappingRequests, launchRequest)
}
}
iamInstanceProfile := aws.String(state.Get("iamInstanceProfile").(string))
@@ -195,7 +194,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
}
// Convert tags from the tag map provided by the user into *ec2.Tag s
ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
ec2Tags, err := s.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error generating tags for source instance: %s", err)
state.Put("error", err)
@@ -325,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 {
@@ -342,7 +336,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
instance := describeOutput.Reservations[0].Instances[0]
// Tag the spot instance request (not the eventual spot instance)
spotTags, err := TagMap(s.SpotTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
spotTags, err := s.SpotTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error generating tags for spot request: %s", err)
state.Put("error", err)
@@ -350,7 +344,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
return multistep.ActionHalt
}
if len(spotTags) > 0 && len(s.SpotTags) > 0 {
if len(spotTags) > 0 && s.SpotTags.IsSet() {
spotTags.Report(ui)
// Use the instance ID to find out the SIR, so that we can tag the spot
// request associated with this instance.
@@ -378,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
@@ -406,10 +400,10 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
}
}
if len(volumeIds) > 0 && len(s.VolumeTags) > 0 {
if len(volumeIds) > 0 && s.VolumeTags.IsSet() {
ui.Say("Adding tags to source EBS Volumes")
volumeTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
volumeTags, err := s.VolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging source EBS Volumes on %s: %s", *instance.InstanceId, err)
state.Put("error", err)
@@ -467,7 +461,7 @@ func (s *StepRunSpotInstance) Cleanup(state multistep.StateBag) {
return
}
if err := s.PollingConfig.WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil {
if err := WaitUntilInstanceTerminated(aws.BackgroundContext(), ec2conn, s.instanceId); err != nil {
ui.Error(err.Error())
}
}
@@ -29,7 +29,6 @@ func tStateSpot() multistep.StateBag {
func getBasicStep() *StepRunSpotInstance {
stepRunSpotInstance := StepRunSpotInstance{
PollingConfig: new(AWSPollingConfig),
AssociatePublicIpAddress: false,
LaunchMappings: BlockDevices{},
BlockDurationMinutes: 0,
@@ -45,9 +44,9 @@ func getBasicStep() *StepRunSpotInstance {
InstanceType: "t2.micro",
SourceAMI: "",
SpotPrice: "auto",
SpotTags: nil,
Tags: map[string]string{},
VolumeTags: nil,
SpotTags: TagMap(nil),
Tags: TagMap{},
VolumeTags: TagMap(nil),
UserData: "",
UserDataFile: "",
}
@@ -95,42 +94,3 @@ func TestCreateTemplateData(t *testing.T) {
t.Fatalf("Template shouldn't contain instance profile if iamInstanceProfile is unset.")
}
}
func TestCreateTemplateData_NoEphemeral(t *testing.T) {
state := tStateSpot()
stepRunSpotInstance := getBasicStep()
stepRunSpotInstance.NoEphemeral = true
template := stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state,
&ec2.LaunchTemplateInstanceMarketOptionsRequest{})
if len(template.BlockDeviceMappings) != 26 {
t.Fatalf("Should have created 26 mappings to keep ephemeral drives from appearing.")
}
// Now check that noEphemeral doesn't mess with the mappings in real life.
// state = tStateSpot()
// stepRunSpotInstance = getBasicStep()
// stepRunSpotInstance.NoEphemeral = true
// mappings := []*ec2.InstanceBlockDeviceMapping{
// &ec2.InstanceBlockDeviceMapping{
// DeviceName: "xvda",
// Ebs: {
// DeleteOnTermination: true,
// Status: "attaching",
// VolumeId: "vol-044cd49c330f21c05",
// },
// },
// &ec2.InstanceBlockDeviceMapping{
// DeviceName: "/dev/xvdf",
// Ebs: {
// DeleteOnTermination: false,
// Status: "attaching",
// VolumeId: "vol-0eefaf2d6ae35827e",
// },
// },
// }
// template = stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state,
// &ec2.LaunchTemplateInstanceMarketOptionsRequest{})
// if len(*template.BlockDeviceMappings) != 26 {
// t.Fatalf("Should have created 26 mappings to keep ephemeral drives from appearing.")
// }
}
+14 -13
View File
@@ -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
}
@@ -1,29 +0,0 @@
package common
import (
"context"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder"
"github.com/hashicorp/packer/helper/multistep"
)
// &awscommon.StepSetGeneratedData{
// GeneratedData: generatedData,
// },
type StepSetGeneratedData struct {
GeneratedData *builder.GeneratedData
}
func (s *StepSetGeneratedData) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(*ec2.EC2)
extractBuildInfo(*ec2conn.Config.Region, state, s.GeneratedData)
return multistep.ActionContinue
}
func (s *StepSetGeneratedData) Cleanup(state multistep.StateBag) {
// No cleanup...
}
@@ -12,7 +12,6 @@ import (
)
type StepStopEBSBackedInstance struct {
PollingConfig *AWSPollingConfig
Skip bool
DisableStopInstance bool
}
@@ -42,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
@@ -75,7 +74,7 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta
&ec2.DescribeInstancesInput{
InstanceIds: []*string{instance.InstanceId},
},
s.PollingConfig.getWaiterOptions()...)
getWaiterOptions()...)
if err != nil {
err := fmt.Errorf("Error waiting for instance to stop: %s", err)
+4
View File
@@ -21,6 +21,10 @@ func (t EC2Tags) Report(ui packer.Ui) {
}
}
func (t TagMap) IsSet() bool {
return len(t) > 0
}
func (t TagMap) EC2Tags(ictx interpolate.Context, region string, state multistep.StateBag) (EC2Tags, error) {
var ec2Tags []*ec2.Tag
generatedData := builder.GeneratedData{State: state}
@@ -1,61 +0,0 @@
package amazon_acc
// This is the code necessary for running the provisioner acceptance tests.
// It provides the builder config and cleans up created resource.
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
amazonebsbuilder "github.com/hashicorp/packer/builder/amazon/ebs"
"github.com/hashicorp/packer/packer"
testshelper "github.com/hashicorp/packer/helper/tests"
)
type AmazonEBSAccTest struct{}
func (s *AmazonEBSAccTest) GetConfigs() (map[string]string, error) {
fixtures := map[string]string{
"linux": "amazon-ebs.txt",
"windows": "amazon-ebs_windows.txt",
}
configs := make(map[string]string)
for distro, fixture := range fixtures {
fileName := fixture
filePath := filepath.Join("../../builder/amazon/ebs/acceptance/test-fixtures/", fileName)
config, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("Expected to find %s", filePath)
}
defer config.Close()
file, err := ioutil.ReadAll(config)
if err != nil {
return nil, fmt.Errorf("Unable to read %s", filePath)
}
configs[distro] = string(file)
}
return configs, nil
}
func (s *AmazonEBSAccTest) CleanUp() error {
helper := testshelper.AWSHelper{
Region: "us-east-1",
AMIName: "packer-acc-test",
}
return helper.CleanUpAmi()
}
func (s *AmazonEBSAccTest) GetBuilderStore() packer.MapOfBuilder {
return packer.MapOfBuilder{
"amazon-ebs": func() (packer.Builder, error) { return &amazonebsbuilder.Builder{}, nil },
}
}
@@ -1,12 +0,0 @@
{
"type": "amazon-ebs",
"ami_name": "packer-acc-test",
"instance_type": "m1.small",
"region": "us-east-1",
"ssh_username": "ubuntu",
"source_ami": "ami-0568456c",
"force_deregister" : true,
"tags": {
"packer-test": "true"
}
}
@@ -1,23 +0,0 @@
{
"type": "amazon-ebs",
"region": "us-east-1",
"instance_type": "t2.micro",
"source_ami_filter": {
"filters": {
"virtualization-type": "hvm",
"name": "*Windows_Server-2012-R2*English-64Bit-Base*",
"root-device-type": "ebs"
},
"most_recent": true,
"owners": "amazon"
},
"ami_name": "packer-acc-test",
"user_data_file": "../../builder/amazon/ebs/acceptance/test-fixtures/scripts/bootstrap_win.txt",
"communicator": "winrm",
"winrm_username": "Administrator",
"winrm_password": "SuperS3cr3t!!!!",
"force_deregister" : true,
"tags": {
"packer-test": "true"
}
}
@@ -1,40 +0,0 @@
<powershell>
# Set administrator password
net user Administrator SuperS3cr3t!!!!
wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE
# First, make sure WinRM can't be connected to
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block
# Delete any existing WinRM listeners
winrm delete winrm/config/listener?Address=*+Transport=HTTP 2>$Null
winrm delete winrm/config/listener?Address=*+Transport=HTTPS 2>$Null
# Disable group policies which block basic authentication and unencrypted login
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Client -Name AllowBasic -Value 1
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Client -Name AllowUnencryptedTraffic -Value 1
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Service -Name AllowBasic -Value 1
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Service -Name AllowUnencryptedTraffic -Value 1
# Create a new WinRM listener and configure
winrm create winrm/config/listener?Address=*+Transport=HTTP
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="0"}'
winrm set winrm/config '@{MaxTimeoutms="7200000"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
winrm set winrm/config/service '@{MaxConcurrentOperationsPerUser="12000"}'
winrm set winrm/config/service/auth '@{Basic="true"}'
winrm set winrm/config/client/auth '@{Basic="true"}'
# Configure UAC to allow privilege elevation in remote shells
$Key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
$Setting = 'LocalAccountTokenFilterPolicy'
Set-ItemProperty -Path $Key -Name $Setting -Value 1 -Force
# Configure and restart the WinRM Service; Enable the required firewall exception
Stop-Service -Name WinRM
Set-Service -Name WinRM -StartupType Automatic
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new action=allow localip=any remoteip=any
Start-Service -Name WinRM
</powershell>
+4 -31
View File
@@ -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"
@@ -53,14 +52,9 @@ type Config struct {
// Tags to apply to the volumes that are *launched* to create the AMI.
// These tags are *not* applied to the resulting AMI unless they're
// duplicated in `tags`. This is a [template
// engine](/docs/templates/engine), see [Build template
// engine](/docs/templates/engine.html), 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)...)
@@ -140,7 +132,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
generatedData := awscommon.GetGeneratedDataList()
generatedData := []string{"SourceAMIName"}
return generatedData, warns, nil
}
@@ -169,7 +161,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
if b.config.IsSpotInstance() {
instanceStep = &awscommon.StepRunSpotInstance{
PollingConfig: b.config.PollingConfig,
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
LaunchMappings: b.config.LaunchMappings,
BlockDurationMinutes: b.config.BlockDurationMinutes,
@@ -192,7 +183,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
} else {
instanceStep = &awscommon.StepRunSourceInstance{
PollingConfig: b.config.PollingConfig,
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
LaunchMappings: b.config.LaunchMappings,
Comm: &b.config.RunConfig.Comm,
@@ -221,7 +211,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
VpcId: b.config.VpcId,
SubnetId: b.config.SubnetId,
HasSubnetFilter: !b.config.SubnetFilter.Empty(),
HasSubnetFilter: len(b.config.SubnetFilter.Filters) > 0,
},
&awscommon.StepSourceAMIInfo{
SourceAmi: b.config.SourceAmi,
@@ -249,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,
@@ -266,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(
@@ -280,21 +262,13 @@ 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(),
},
&awscommon.StepSetGeneratedData{
GeneratedData: generatedData,
},
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.RunConfig.Comm,
},
&awscommon.StepStopEBSBackedInstance{
PollingConfig: b.config.PollingConfig,
Skip: b.config.IsSpotInstance(),
DisableStopInstance: b.config.DisableStopInstance,
},
@@ -311,7 +285,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
},
&stepCreateAMI{
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
PollingConfig: b.config.PollingConfig,
},
&awscommon.StepAMIRegionCopy{
AccessConfig: &b.config.AccessConfig,
+120 -149
View File
@@ -4,140 +4,125 @@ package ebs
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/hcl2template"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
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 common.TagMap `mapstructure:"tags" required:"false" cty:"tags"`
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
SnapshotTags common.TagMap `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address"`
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone"`
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes"`
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter"`
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"`
LaunchMappings []common.FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings"`
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.
@@ -157,7 +142,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
@@ -172,7 +157,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
"ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
"ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false},
"ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false},
@@ -180,18 +164,16 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false},
"ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false},
"ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false},
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
"force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false},
"encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false},
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(cty.String), Required: false},
"region_kms_key_ids": &hcldec.BlockAttrsSpec{TypeName: "region_kms_key_ids", ElementType: cty.String, Required: false},
"skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false},
"snapshot_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
"snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false},
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
@@ -206,8 +188,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
"instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false},
"security_group_filter": &hcldec.BlockSpec{TypeName: "security_group_filter", Nested: hcldec.ObjectSpec((*common.FlatSecurityGroupFilterOptions)(nil).HCL2Spec())},
"run_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "run_tags", ElementType: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_ids": &hcldec.AttrSpec{Name: "security_group_ids", Type: cty.List(cty.String), Required: false},
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
@@ -215,8 +196,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"spot_instance_types": &hcldec.AttrSpec{Name: "spot_instance_types", Type: cty.List(cty.String), Required: false},
"spot_price": &hcldec.AttrSpec{Name: "spot_price", Type: cty.String, Required: false},
"spot_price_auto_product": &hcldec.AttrSpec{Name: "spot_price_auto_product", Type: cty.String, Required: false},
"spot_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "spot_tags", ElementType: cty.String, Required: false},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
@@ -233,14 +213,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,9 +225,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"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},
@@ -266,18 +240,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())},
"run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "run_volume_tags", ElementType: cty.String, Required: false},
"no_ephemeral": &hcldec.AttrSpec{Name: "no_ephemeral", Type: cty.Bool, Required: false},
}
return s
-18
View File
@@ -144,25 +144,7 @@ func TestBuilderPrepare_ReturnGeneratedData(t *testing.T) {
if len(generatedData) == 0 {
t.Fatalf("Generated data should not be empty")
}
if len(generatedData) == 0 {
t.Fatalf("Generated data should not be empty")
}
if generatedData[0] != "SourceAMIName" {
t.Fatalf("Generated data should contain SourceAMIName")
}
if generatedData[1] != "BuildRegion" {
t.Fatalf("Generated data should contain BuildRegion")
}
if generatedData[2] != "SourceAMI" {
t.Fatalf("Generated data should contain SourceAMI")
}
if generatedData[3] != "SourceAMICreationDate" {
t.Fatalf("Generated data should contain SourceAMICreationDate")
}
if generatedData[4] != "SourceAMIOwner" {
t.Fatalf("Generated data should contain SourceAMIOwner")
}
if generatedData[5] != "SourceAMIOwnerName" {
t.Fatalf("Generated data should contain SourceAMIOwnerName")
}
}
+6 -33
View File
@@ -4,19 +4,16 @@ 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"
)
type stepCreateAMI struct {
PollingConfig *awscommon.AWSPollingConfig
image *ec2.Image
AMISkipBuildRegion bool
}
@@ -51,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)
@@ -86,23 +64,18 @@ func (s *stepCreateAMI) Run(ctx context.Context, state multistep.StateBag) multi
// Wait for the image to become ready
ui.Say("Waiting for AMI to become ready...")
if waitErr := s.PollingConfig.WaitUntilAMIAvailable(ctx, ec2conn, *createResp.ImageId); waitErr != nil {
// waitErr should get bubbled up if the issue is a wait timeout
err := fmt.Errorf("Error waiting for AMI: %s", waitErr)
if err := awscommon.WaitUntilAMIAvailable(ctx, ec2conn, *createResp.ImageId); err != nil {
log.Printf("Error waiting for AMI: %s", err)
imResp, imerr := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{createResp.ImageId}})
if imerr != nil {
// If there's a failure describing images, bubble that error up too, but don't erase the waitErr.
log.Printf("DescribeImages call was unable to determine reason waiting for AMI failed: %s", imerr)
err = fmt.Errorf("Unknown error waiting for AMI; %s. DescribeImages returned an error: %s", waitErr, imerr)
log.Printf("Unable to determine reason waiting for AMI failed: %s", err)
err = fmt.Errorf("Unknown error waiting for AMI; %s", err)
}
if imResp != nil && len(imResp.Images) > 0 {
// Finally, if there's a stateReason, store that with the wait err
image := imResp.Images[0]
if image != nil {
stateReason := image.StateReason
if stateReason != nil {
err = fmt.Errorf("Error waiting for AMI: %s. DescribeImages returned the state reason: %s", waitErr, stateReason)
}
err = fmt.Errorf("Error waiting for AMI. Reason: %s", stateReason)
}
}
state.Put("error", err)
+15 -45
View File
@@ -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"
@@ -59,14 +58,9 @@ type Config struct {
// Tags to apply to the volumes that are *launched* to create the AMI.
// These tags are *not* applied to the resulting AMI unless they're
// duplicated in `tags`. This is a [template
// engine](/docs/templates/engine), see [Build template
// engine](/docs/templates/engine.html), 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,
@@ -163,7 +155,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
generatedData := awscommon.GetGeneratedDataList()
generatedData := []string{"SourceAMIName"}
return generatedData, warns, nil
}
@@ -192,7 +184,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
if b.config.IsSpotInstance() {
instanceStep = &awscommon.StepRunSpotInstance{
PollingConfig: b.config.PollingConfig,
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
LaunchMappings: b.config.LaunchMappings,
BlockDurationMinutes: b.config.BlockDurationMinutes,
@@ -214,7 +205,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
} else {
instanceStep = &awscommon.StepRunSourceInstance{
PollingConfig: b.config.PollingConfig,
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
LaunchMappings: b.config.LaunchMappings,
Comm: &b.config.RunConfig.Comm,
@@ -240,12 +230,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
// Build the steps
steps := []multistep.Step{
&awscommon.StepPreValidate{
DestAmiName: b.config.AMIName,
ForceDeregister: b.config.AMIForceDeregister,
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
VpcId: b.config.VpcId,
SubnetId: b.config.SubnetId,
HasSubnetFilter: !b.config.SubnetFilter.Empty(),
DestAmiName: b.config.AMIName,
ForceDeregister: b.config.AMIForceDeregister,
VpcId: b.config.VpcId,
SubnetId: b.config.SubnetId,
HasSubnetFilter: len(b.config.SubnetFilter.Filters) > 0,
},
&awscommon.StepSourceAMIInfo{
SourceAmi: b.config.SourceAmi,
@@ -273,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,
@@ -290,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(
@@ -304,21 +285,13 @@ 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(),
},
&awscommon.StepSetGeneratedData{
GeneratedData: generatedData,
},
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.RunConfig.Comm,
},
&awscommon.StepStopEBSBackedInstance{
PollingConfig: b.config.PollingConfig,
Skip: b.config.IsSpotInstance(),
DisableStopInstance: b.config.DisableStopInstance,
},
@@ -328,7 +301,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
EnableAMIENASupport: b.config.AMIENASupport,
},
&StepSnapshotVolumes{
PollingConfig: b.config.PollingConfig,
LaunchDevices: launchDevices,
SnapshotOmitMap: b.config.LaunchMappings.GetOmissions(),
},
@@ -348,17 +320,15 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Architecture: b.config.Architecture,
LaunchOmitMap: b.config.LaunchMappings.GetOmissions(),
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
PollingConfig: b.config.PollingConfig,
},
&awscommon.StepAMIRegionCopy{
AccessConfig: &b.config.AccessConfig,
Regions: b.config.AMIRegions,
AMIKmsKeyId: b.config.AMIKmsKeyId,
RegionKeyIds: b.config.AMIRegionKMSKeyIDs,
EncryptBootVolume: b.config.AMIEncryptBootVolume,
Name: b.config.AMIName,
OriginalRegion: *ec2conn.Config.Region,
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
AccessConfig: &b.config.AccessConfig,
Regions: b.config.AMIRegions,
AMIKmsKeyId: b.config.AMIKmsKeyId,
RegionKeyIds: b.config.AMIRegionKMSKeyIDs,
EncryptBootVolume: b.config.AMIEncryptBootVolume,
Name: b.config.AMIName,
OriginalRegion: *ec2conn.Config.Region,
},
&awscommon.StepModifyAMIAttributes{
Description: b.config.AMIDescription,
+138 -167
View File
@@ -4,24 +4,23 @@ package ebssurrogate
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/hcl2template"
"github.com/zclconf/go-cty/cty"
)
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatBlockDevice struct {
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" 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,134 +53,120 @@ 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"`
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
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"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
AMIName *string `mapstructure:"ami_name" required:"true" cty:"ami_name"`
AMIDescription *string `mapstructure:"ami_description" required:"false" cty:"ami_description"`
AMIVirtType *string `mapstructure:"ami_virtualization_type" required:"false" cty:"ami_virtualization_type"`
AMIUsers []string `mapstructure:"ami_users" required:"false" cty:"ami_users"`
AMIGroups []string `mapstructure:"ami_groups" required:"false" cty:"ami_groups"`
AMIProductCodes []string `mapstructure:"ami_product_codes" required:"false" cty:"ami_product_codes"`
AMIRegions []string `mapstructure:"ami_regions" required:"false" cty:"ami_regions"`
AMITags common.TagMap `mapstructure:"tags" required:"false" cty:"tags"`
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
SnapshotTags common.TagMap `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"`
LaunchMappings []FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings"`
RootDevice *FlatRootBlockDevice `mapstructure:"ami_root_device" required:"true" cty:"ami_root_device"`
VolumeRunTags common.TagMap `mapstructure:"run_volume_tags" cty:"run_volume_tags"`
Architecture *string `mapstructure:"ami_architecture" required:"false" cty:"ami_architecture"`
}
// FlatMapstructure returns a new FlatConfig.
@@ -201,7 +186,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
@@ -216,7 +201,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
"availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false},
"block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false},
@@ -229,8 +213,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
"instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false},
"security_group_filter": &hcldec.BlockSpec{TypeName: "security_group_filter", Nested: hcldec.ObjectSpec((*common.FlatSecurityGroupFilterOptions)(nil).HCL2Spec())},
"run_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "run_tags", ElementType: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_ids": &hcldec.AttrSpec{Name: "security_group_ids", Type: cty.List(cty.String), Required: false},
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
@@ -238,8 +221,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"spot_instance_types": &hcldec.AttrSpec{Name: "spot_instance_types", Type: cty.List(cty.String), Required: false},
"spot_price": &hcldec.AttrSpec{Name: "spot_price", Type: cty.String, Required: false},
"spot_price_auto_product": &hcldec.AttrSpec{Name: "spot_price_auto_product", Type: cty.String, Required: false},
"spot_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "spot_tags", ElementType: cty.String, Required: false},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
@@ -256,14 +238,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,9 +250,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"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},
@@ -289,14 +265,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},
@@ -304,25 +278,22 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false},
"ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false},
"ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false},
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
"force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false},
"encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false},
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(cty.String), Required: false},
"region_kms_key_ids": &hcldec.BlockAttrsSpec{TypeName: "region_kms_key_ids", ElementType: cty.String, Required: false},
"skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false},
"snapshot_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
"snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false},
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
"ami_block_device_mappings": &hcldec.BlockListSpec{TypeName: "ami_block_device_mappings", Nested: hcldec.ObjectSpec((*common.FlatBlockDevice)(nil).HCL2Spec())},
"launch_block_device_mappings": &hcldec.BlockListSpec{TypeName: "launch_block_device_mappings", Nested: hcldec.ObjectSpec((*FlatBlockDevice)(nil).HCL2Spec())},
"ami_root_device": &hcldec.BlockSpec{TypeName: "ami_root_device", Nested: hcldec.ObjectSpec((*FlatRootBlockDevice)(nil).HCL2Spec())},
"run_volume_tags": &hcldec.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())},
"run_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "run_volume_tags", ElementType: cty.String, Required: false},
"ami_architecture": &hcldec.AttrSpec{Name: "ami_architecture", Type: cty.String, Required: false},
}
return s
@@ -331,12 +302,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.
@@ -86,25 +86,7 @@ func TestBuilderPrepare_ReturnGeneratedData(t *testing.T) {
if len(generatedData) == 0 {
t.Fatalf("Generated data should not be empty")
}
if len(generatedData) == 0 {
t.Fatalf("Generated data should not be empty")
}
if generatedData[0] != "SourceAMIName" {
t.Fatalf("Generated data should contain SourceAMIName")
}
if generatedData[1] != "BuildRegion" {
t.Fatalf("Generated data should contain BuildRegion")
}
if generatedData[2] != "SourceAMI" {
t.Fatalf("Generated data should contain SourceAMI")
}
if generatedData[3] != "SourceAMICreationDate" {
t.Fatalf("Generated data should contain SourceAMICreationDate")
}
if generatedData[4] != "SourceAMIOwner" {
t.Fatalf("Generated data should contain SourceAMIOwner")
}
if generatedData[5] != "SourceAMIOwnerName" {
t.Fatalf("Generated data should contain SourceAMIOwnerName")
}
}
@@ -15,7 +15,6 @@ import (
// StepRegisterAMI creates the AMI.
type StepRegisterAMI struct {
PollingConfig *awscommon.AWSPollingConfig
RootDevice RootBlockDevice
AMIDevices []*ec2.BlockDeviceMapping
LaunchDevices []*ec2.BlockDeviceMapping
@@ -87,7 +86,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul
// Wait for the image to become ready
ui.Say("Waiting for AMI to become ready...")
if err := s.PollingConfig.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
if err := awscommon.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
err := fmt.Errorf("Error waiting for AMI: %s", err)
state.Put("error", err)
ui.Error(err.Error())
@@ -7,7 +7,6 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder/amazon/common"
)
const sourceDeviceName = "/dev/xvdf"
@@ -24,7 +23,6 @@ func newStepRegisterAMI(amiDevices, launchDevices []*ec2.BlockDeviceMapping) *St
},
AMIDevices: amiDevices,
LaunchDevices: launchDevices,
PollingConfig: new(common.AWSPollingConfig),
}
}
@@ -18,7 +18,6 @@ import (
// Produces:
// snapshot_ids map[string]string - IDs of the created snapshots
type StepSnapshotVolumes struct {
PollingConfig *awscommon.AWSPollingConfig
LaunchDevices []*ec2.BlockDeviceMapping
snapshotIds map[string]string
snapshotMutex sync.Mutex
@@ -57,7 +56,7 @@ func (s *StepSnapshotVolumes) snapshotVolume(ctx context.Context, deviceName str
s.snapshotMutex.Unlock()
// Wait for snapshot to be created
err = s.PollingConfig.WaitUntilSnapshotDone(ctx, ec2conn, *createSnapResp.SnapshotId)
err = awscommon.WaitUntilSnapshotDone(ctx, ec2conn, *createSnapResp.SnapshotId)
return err
}
+3 -14
View File
@@ -5,21 +5,15 @@ package ebsvolume
import (
"github.com/aws/aws-sdk-go/service/ec2"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/template/interpolate"
)
type BlockDevice struct {
awscommon.BlockDevice `mapstructure:",squash"`
// Key/value pair tags to apply to the volume. These are retained after the builder
// completes. This is a [template engine](/docs/templates/engine), see
// Tags to apply to the volume. These are retained after the builder
// completes. This is a [template engine](/docs/templates/engine.html), 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
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
// will allow you to create those programatically.
Tag hcl2template.KeyValues `mapstructure:"tag" required:"false"`
Tags awscommon.TagMap `mapstructure:"tags" required:"false"`
}
type BlockDevices []BlockDevice
@@ -34,15 +28,10 @@ func (bds BlockDevices) BuildEC2BlockDeviceMappings() []*ec2.BlockDeviceMapping
}
func (bds BlockDevices) Prepare(ctx *interpolate.Context) (errs []error) {
for _, block := range bds {
errs = append(errs, block.Tag.CopyOn(&block.Tags)...)
if err := block.Prepare(ctx); err != nil {
errs = append(errs, err)
}
}
return errs
}
+7 -35
View File
@@ -12,10 +12,8 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/hcl/v2/hcldec"
"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"
@@ -54,11 +52,11 @@ 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
// engine](/docs/templates/engine), see [Build 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.html), see [Build template
// data](#build-template-data) for more information.
//
// Note: The tags specified here will be *temporarily* applied to volumes
@@ -66,13 +64,7 @@ type Config struct {
// created. Packer will replace all tags on the volume with the tags
// configured in the `ebs_volumes` section as soon as the instance is
// 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
// 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"`
VolumeRunTags awscommon.TagMap `mapstructure:"run_volume_tags"`
launchBlockDevices BlockDevices
@@ -110,7 +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, b.config.launchBlockDevices.Prepare(&b.config.ctx)...)
@@ -147,7 +138,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
generatedData := awscommon.GetGeneratedDataList()
generatedData := []string{"SourceAMIName"}
return generatedData, warns, nil
}
@@ -167,13 +158,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state.Put("iam", iam)
state.Put("hook", hook)
state.Put("ui", ui)
generatedData := &builder.GeneratedData{State: state}
var instanceStep multistep.Step
if b.config.IsSpotInstance() {
instanceStep = &awscommon.StepRunSpotInstance{
PollingConfig: b.config.PollingConfig,
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
LaunchMappings: b.config.launchBlockDevices,
BlockDurationMinutes: b.config.BlockDurationMinutes,
@@ -195,7 +184,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
} else {
instanceStep = &awscommon.StepRunSourceInstance{
PollingConfig: b.config.PollingConfig,
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
LaunchMappings: b.config.launchBlockDevices,
Comm: &b.config.RunConfig.Comm,
@@ -242,7 +230,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,
@@ -260,13 +247,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(
@@ -274,21 +254,13 @@ 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(),
},
&awscommon.StepSetGeneratedData{
GeneratedData: generatedData,
},
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.RunConfig.Comm,
},
&awscommon.StepStopEBSBackedInstance{
PollingConfig: b.config.PollingConfig,
Skip: b.config.IsSpotInstance(),
DisableStopInstance: b.config.DisableStopInstance,
},
+110 -137
View File
@@ -4,25 +4,23 @@ package ebsvolume
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/hcl2template"
"github.com/zclconf/go-cty/cty"
)
// FlatBlockDevice is an auto-generated flat version of BlockDevice.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatBlockDevice struct {
DeleteOnTermination *bool `mapstructure:"delete_on_termination" required:"false" cty:"delete_on_termination" 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 common.TagMap `mapstructure:"tags" required:"false" cty:"tags"`
}
// FlatMapstructure returns a new FlatBlockDevice.
@@ -47,8 +45,7 @@ func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
"volume_type": &hcldec.AttrSpec{Name: "volume_type", Type: cty.String, Required: false},
"volume_size": &hcldec.AttrSpec{Name: "volume_size", Type: cty.Number, Required: false},
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
}
return s
}
@@ -56,112 +53,100 @@ 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"`
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
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"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
VolumeMappings []FlatBlockDevice `mapstructure:"ebs_volumes" required:"false" cty:"ebs_volumes"`
VolumeRunTags common.TagMap `mapstructure:"run_volume_tags" cty:"run_volume_tags"`
}
// FlatMapstructure returns a new FlatConfig.
@@ -181,7 +166,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
@@ -196,7 +181,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
"availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false},
"block_duration_minutes": &hcldec.AttrSpec{Name: "block_duration_minutes", Type: cty.Number, Required: false},
@@ -209,8 +193,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
"instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false},
"security_group_filter": &hcldec.BlockSpec{TypeName: "security_group_filter", Nested: hcldec.ObjectSpec((*common.FlatSecurityGroupFilterOptions)(nil).HCL2Spec())},
"run_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "run_tags", ElementType: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_ids": &hcldec.AttrSpec{Name: "security_group_ids", Type: cty.List(cty.String), Required: false},
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
@@ -218,8 +201,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"spot_instance_types": &hcldec.AttrSpec{Name: "spot_instance_types", Type: cty.List(cty.String), Required: false},
"spot_price": &hcldec.AttrSpec{Name: "spot_price", Type: cty.String, Required: false},
"spot_price_auto_product": &hcldec.AttrSpec{Name: "spot_price_auto_product", Type: cty.String, Required: false},
"spot_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "spot_tags", ElementType: cty.String, Required: false},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
@@ -236,14 +218,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,9 +230,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"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},
@@ -269,19 +245,16 @@ 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_tags": &hcldec.BlockAttrsSpec{TypeName: "run_volume_tags", ElementType: cty.String, Required: false},
}
return s
}
-18
View File
@@ -105,25 +105,7 @@ func TestBuilderPrepare_ReturnGeneratedData(t *testing.T) {
if len(generatedData) == 0 {
t.Fatalf("Generated data should not be empty")
}
if len(generatedData) == 0 {
t.Fatalf("Generated data should not be empty")
}
if generatedData[0] != "SourceAMIName" {
t.Fatalf("Generated data should contain SourceAMIName")
}
if generatedData[1] != "BuildRegion" {
t.Fatalf("Generated data should contain BuildRegion")
}
if generatedData[2] != "SourceAMI" {
t.Fatalf("Generated data should contain SourceAMI")
}
if generatedData[3] != "SourceAMICreationDate" {
t.Fatalf("Generated data should contain SourceAMICreationDate")
}
if generatedData[4] != "SourceAMIOwner" {
t.Fatalf("Generated data should contain SourceAMIOwner")
}
if generatedData[5] != "SourceAMIOwnerName" {
t.Fatalf("Generated data should contain SourceAMIOwnerName")
}
}
@@ -7,7 +7,6 @@ import (
"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/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
@@ -44,11 +43,11 @@ func (s *stepTagEBSVolumes) Run(ctx context.Context, state multistep.StateBag) m
// volume will have had these tags applied when the instance was
// created. We now need to remove these tags to ensure only the EBS
// volume tags are applied (if any)
if len(config.VolumeRunTags) > 0 {
if config.VolumeRunTags.IsSet() {
ui.Say("Removing any tags applied to EBS volumes when the source instance was created...")
ui.Message("Compiling list of existing tags to remove...")
existingTags, err := awscommon.TagMap(config.VolumeRunTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
existingTags, err := config.VolumeRunTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error generating list of tags to remove: %s", err)
state.Put("error", err)
@@ -92,7 +91,7 @@ func (s *stepTagEBSVolumes) Run(ctx context.Context, state multistep.StateBag) m
}
ui.Message(fmt.Sprintf("Compiling list of tags to apply to volume on %s...", mapping.DeviceName))
tags, err := awscommon.TagMap(mapping.Tags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
tags, err := mapping.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error generating tags for device %s: %s", mapping.DeviceName, err)
state.Put("error", err)
+3 -23
View File
@@ -61,7 +61,7 @@ type Config struct {
// exist and be writable.
BundleDestination string `mapstructure:"bundle_destination" required:"false"`
// The prefix for files created from bundling the root volume. By default
// this is `image-{{timestamp}}`. The timestamp variable should be used to
// this is image-{{timestamp}}. The timestamp variable should be used to
// make sure this is unique, otherwise it can collide with other created
// AMIs by Packer in your account.
BundlePrefix string `mapstructure:"bundle_prefix" required:"false"`
@@ -227,7 +227,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
}
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
generatedData := awscommon.GetGeneratedDataList()
generatedData := []string{"SourceAMIName"}
return generatedData, warns, nil
}
@@ -255,7 +255,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
if b.config.IsSpotInstance() {
instanceStep = &awscommon.StepRunSpotInstance{
PollingConfig: b.config.PollingConfig,
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
LaunchMappings: b.config.LaunchMappings,
BlockDurationMinutes: b.config.BlockDurationMinutes,
@@ -274,7 +273,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
} else {
instanceStep = &awscommon.StepRunSourceInstance{
PollingConfig: b.config.PollingConfig,
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
LaunchMappings: b.config.LaunchMappings,
Comm: &b.config.RunConfig.Comm,
@@ -298,7 +296,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
ForceDeregister: b.config.AMIForceDeregister,
VpcId: b.config.VpcId,
SubnetId: b.config.SubnetId,
HasSubnetFilter: !b.config.SubnetFilter.Empty(),
HasSubnetFilter: len(b.config.SubnetFilter.Filters) > 0,
},
&awscommon.StepSourceAMIInfo{
SourceAmi: b.config.SourceAmi,
@@ -326,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,
@@ -340,31 +337,15 @@ 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(),
},
&awscommon.StepSetGeneratedData{
GeneratedData: generatedData,
},
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.RunConfig.Comm,
@@ -387,7 +368,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
EnableAMIENASupport: b.config.AMIENASupport,
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
PollingConfig: b.config.PollingConfig,
},
&awscommon.StepAMIRegionCopy{
AccessConfig: &b.config.AccessConfig,
+126 -153
View File
@@ -4,146 +4,132 @@ package instance
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/hcl2template"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
PollingConfig *common.FlatAWSPollingConfig `mapstructure:"aws_polling" required:"false" cty:"aws_polling" hcl:"aws_polling"`
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 common.TagMap `mapstructure:"tags" required:"false" cty:"tags"`
AMIENASupport *bool `mapstructure:"ena_support" required:"false" cty:"ena_support"`
AMISriovNetSupport *bool `mapstructure:"sriov_support" required:"false" cty:"sriov_support"`
AMIForceDeregister *bool `mapstructure:"force_deregister" required:"false" cty:"force_deregister"`
AMIForceDeleteSnapshot *bool `mapstructure:"force_delete_snapshot" required:"false" cty:"force_delete_snapshot"`
AMIEncryptBootVolume *bool `mapstructure:"encrypt_boot" required:"false" cty:"encrypt_boot"`
AMIKmsKeyId *string `mapstructure:"kms_key_id" required:"false" cty:"kms_key_id"`
AMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids" required:"false" cty:"region_kms_key_ids"`
AMISkipBuildRegion *bool `mapstructure:"skip_save_build_region" cty:"skip_save_build_region"`
SnapshotTags common.TagMap `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags"`
SnapshotUsers []string `mapstructure:"snapshot_users" required:"false" cty:"snapshot_users"`
SnapshotGroups []string `mapstructure:"snapshot_groups" required:"false" cty:"snapshot_groups"`
AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address"`
AvailabilityZone *string `mapstructure:"availability_zone" required:"false" cty:"availability_zone"`
BlockDurationMinutes *int64 `mapstructure:"block_duration_minutes" required:"false" cty:"block_duration_minutes"`
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance"`
EbsOptimized *bool `mapstructure:"ebs_optimized" required:"false" cty:"ebs_optimized"`
EnableT2Unlimited *bool `mapstructure:"enable_t2_unlimited" required:"false" cty:"enable_t2_unlimited"`
IamInstanceProfile *string `mapstructure:"iam_instance_profile" required:"false" cty:"iam_instance_profile"`
SkipProfileValidation *bool `mapstructure:"skip_profile_validation" required:"false" cty:"skip_profile_validation"`
TemporaryIamInstanceProfilePolicyDocument *common.FlatPolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false" cty:"temporary_iam_instance_profile_policy_document"`
InstanceInitiatedShutdownBehavior *string `mapstructure:"shutdown_behavior" required:"false" cty:"shutdown_behavior"`
InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type"`
SecurityGroupFilter *common.FlatSecurityGroupFilterOptions `mapstructure:"security_group_filter" required:"false" cty:"security_group_filter"`
RunTags map[string]string `mapstructure:"run_tags" required:"false" cty:"run_tags"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id"`
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false" cty:"security_group_ids"`
SourceAmi *string `mapstructure:"source_ami" required:"true" cty:"source_ami"`
SourceAmiFilter *common.FlatAmiFilterOptions `mapstructure:"source_ami_filter" required:"false" cty:"source_ami_filter"`
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false" cty:"spot_instance_types"`
SpotPrice *string `mapstructure:"spot_price" required:"false" cty:"spot_price"`
SpotPriceAutoProduct *string `mapstructure:"spot_price_auto_product" required:"false" cty:"spot_price_auto_product"`
SpotTags map[string]string `mapstructure:"spot_tags" required:"false" cty:"spot_tags"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data"`
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file"`
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
SSHInterface *string `mapstructure:"ssh_interface" cty:"ssh_interface"`
AMIMappings []common.FlatBlockDevice `mapstructure:"ami_block_device_mappings" required:"false" cty:"ami_block_device_mappings"`
LaunchMappings []common.FlatBlockDevice `mapstructure:"launch_block_device_mappings" required:"false" cty:"launch_block_device_mappings"`
AccountId *string `mapstructure:"account_id" required:"true" cty:"account_id"`
BundleDestination *string `mapstructure:"bundle_destination" required:"false" cty:"bundle_destination"`
BundlePrefix *string `mapstructure:"bundle_prefix" required:"false" cty:"bundle_prefix"`
BundleUploadCommand *string `mapstructure:"bundle_upload_command" required:"false" cty:"bundle_upload_command"`
BundleVolCommand *string `mapstructure:"bundle_vol_command" required:"false" cty:"bundle_vol_command"`
S3Bucket *string `mapstructure:"s3_bucket" required:"true" cty:"s3_bucket"`
X509CertPath *string `mapstructure:"x509_cert_path" required:"true" cty:"x509_cert_path"`
X509KeyPath *string `mapstructure:"x509_key_path" required:"true" cty:"x509_key_path"`
X509UploadPath *string `mapstructure:"x509_upload_path" required:"false" cty:"x509_upload_path"`
}
// FlatMapstructure returns a new FlatConfig.
@@ -163,7 +149,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
"packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false},
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
@@ -178,7 +164,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"vault_aws_engine": &hcldec.BlockSpec{TypeName: "vault_aws_engine", Nested: hcldec.ObjectSpec((*common.FlatVaultAWSEngineOptions)(nil).HCL2Spec())},
"aws_polling": &hcldec.BlockSpec{TypeName: "aws_polling", Nested: hcldec.ObjectSpec((*common.FlatAWSPollingConfig)(nil).HCL2Spec())},
"ami_name": &hcldec.AttrSpec{Name: "ami_name", Type: cty.String, Required: false},
"ami_description": &hcldec.AttrSpec{Name: "ami_description", Type: cty.String, Required: false},
"ami_virtualization_type": &hcldec.AttrSpec{Name: "ami_virtualization_type", Type: cty.String, Required: false},
@@ -186,18 +171,16 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ami_groups": &hcldec.AttrSpec{Name: "ami_groups", Type: cty.List(cty.String), Required: false},
"ami_product_codes": &hcldec.AttrSpec{Name: "ami_product_codes", Type: cty.List(cty.String), Required: false},
"ami_regions": &hcldec.AttrSpec{Name: "ami_regions", Type: cty.List(cty.String), Required: false},
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"tags": &hcldec.BlockAttrsSpec{TypeName: "tags", ElementType: cty.String, Required: false},
"ena_support": &hcldec.AttrSpec{Name: "ena_support", Type: cty.Bool, Required: false},
"sriov_support": &hcldec.AttrSpec{Name: "sriov_support", Type: cty.Bool, Required: false},
"force_deregister": &hcldec.AttrSpec{Name: "force_deregister", Type: cty.Bool, Required: false},
"force_delete_snapshot": &hcldec.AttrSpec{Name: "force_delete_snapshot", Type: cty.Bool, Required: false},
"encrypt_boot": &hcldec.AttrSpec{Name: "encrypt_boot", Type: cty.Bool, Required: false},
"kms_key_id": &hcldec.AttrSpec{Name: "kms_key_id", Type: cty.String, Required: false},
"region_kms_key_ids": &hcldec.AttrSpec{Name: "region_kms_key_ids", Type: cty.Map(cty.String), Required: false},
"region_kms_key_ids": &hcldec.BlockAttrsSpec{TypeName: "region_kms_key_ids", ElementType: cty.String, Required: false},
"skip_save_build_region": &hcldec.AttrSpec{Name: "skip_save_build_region", Type: cty.Bool, Required: false},
"snapshot_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "snapshot_tags", ElementType: cty.String, Required: false},
"snapshot_users": &hcldec.AttrSpec{Name: "snapshot_users", Type: cty.List(cty.String), Required: false},
"snapshot_groups": &hcldec.AttrSpec{Name: "snapshot_groups", Type: cty.List(cty.String), Required: false},
"associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false},
@@ -212,8 +195,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"shutdown_behavior": &hcldec.AttrSpec{Name: "shutdown_behavior", Type: cty.String, Required: false},
"instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false},
"security_group_filter": &hcldec.BlockSpec{TypeName: "security_group_filter", Nested: hcldec.ObjectSpec((*common.FlatSecurityGroupFilterOptions)(nil).HCL2Spec())},
"run_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "run_tags", ElementType: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_ids": &hcldec.AttrSpec{Name: "security_group_ids", Type: cty.List(cty.String), Required: false},
"source_ami": &hcldec.AttrSpec{Name: "source_ami", Type: cty.String, Required: false},
@@ -221,8 +203,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"spot_instance_types": &hcldec.AttrSpec{Name: "spot_instance_types", Type: cty.List(cty.String), Required: false},
"spot_price": &hcldec.AttrSpec{Name: "spot_price", Type: cty.String, Required: false},
"spot_price_auto_product": &hcldec.AttrSpec{Name: "spot_price_auto_product", Type: cty.String, Required: false},
"spot_tags": &hcldec.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_tags": &hcldec.BlockAttrsSpec{TypeName: "spot_tags", ElementType: cty.String, Required: false},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
@@ -239,14 +220,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,9 +232,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"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},
@@ -272,14 +247,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},
-18
View File
@@ -319,25 +319,7 @@ func TestBuilderPrepare_ReturnGeneratedData(t *testing.T) {
if len(generatedData) == 0 {
t.Fatalf("Generated data should not be empty")
}
if len(generatedData) == 0 {
t.Fatalf("Generated data should not be empty")
}
if generatedData[0] != "SourceAMIName" {
t.Fatalf("Generated data should contain SourceAMIName")
}
if generatedData[1] != "BuildRegion" {
t.Fatalf("Generated data should contain BuildRegion")
}
if generatedData[2] != "SourceAMI" {
t.Fatalf("Generated data should contain SourceAMI")
}
if generatedData[3] != "SourceAMICreationDate" {
t.Fatalf("Generated data should contain SourceAMICreationDate")
}
if generatedData[4] != "SourceAMIOwner" {
t.Fatalf("Generated data should contain SourceAMIOwner")
}
if generatedData[5] != "SourceAMIOwnerName" {
t.Fatalf("Generated data should contain SourceAMIOwnerName")
}
}
+1 -2
View File
@@ -14,7 +14,6 @@ import (
)
type StepRegisterAMI struct {
PollingConfig *awscommon.AWSPollingConfig
EnableAMIENASupport confighelper.Trilean
EnableAMISriovNetSupport bool
AMISkipBuildRegion bool
@@ -81,7 +80,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul
// Wait for the image to become ready
ui.Say("Waiting for AMI to become ready...")
if err := s.PollingConfig.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
if err := awscommon.WaitUntilAMIAvailable(ctx, ec2conn, *registerResp.ImageId); err != nil {
err := fmt.Errorf("Error waiting for AMI: %s", err)
state.Put("error", err)
ui.Error(err.Error())
+10 -5
View File
@@ -13,7 +13,6 @@ import (
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute"
newCompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-03-01/compute"
"github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-01-01/network"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-02-01/resources"
armStorage "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage"
@@ -51,7 +50,7 @@ type AzureClient struct {
InspectorMaxLength int
Template *CaptureTemplate
LastError azureErrorResponse
VaultClientDelete keyvault.VaultsClient
VaultClientDelete common.VaultClient
}
func getCaptureResponse(body string) *CaptureTemplate {
@@ -252,9 +251,15 @@ func NewAzureClient(subscriptionID, resourceGroupName, storageAccountName string
azureClient.VaultClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.VaultClient.UserAgent)
azureClient.VaultClient.Client.PollingDuration = PollingDuration
// This client is different than the above because it manages the vault
// itself rather than the contents of the vault.
azureClient.VaultClientDelete = keyvault.NewVaultsClient(subscriptionID)
// TODO(boumenot) - SDK still does not have a full KeyVault client.
// There are two ways that KeyVault has to be accessed, and each one has their own SPN. An authenticated SPN
// is tied to the URL, and the URL associated with getting the secret is different than the URL
// associated with deleting the KeyVault. As a result, I need to have *two* different clients to
// access KeyVault. I did not want to split it into two separate files, so I am starting with this.
//
// I do not like this implementation. It is getting long in the tooth, and should be re-examined now
// that we have a "working" solution.
azureClient.VaultClientDelete = common.NewVaultClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.VaultClientDelete.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.VaultClientDelete.RequestInspector = withInspection(maxlen)
azureClient.VaultClientDelete.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
+14 -7
View File
@@ -111,11 +111,13 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
if b.config.isManagedImage() {
_, err := azureClient.GroupsClient.Get(ctx, b.config.ManagedImageResourceGroupName)
group, err := azureClient.GroupsClient.Get(ctx, b.config.ManagedImageResourceGroupName)
if err != nil {
return nil, fmt.Errorf("Cannot locate the managed image resource group %s.", b.config.ManagedImageResourceGroupName)
}
b.config.manageImageLocation = *group.Location
// If a managed image already exists it cannot be overwritten.
_, err = azureClient.ImagesClient.Get(ctx, b.config.ManagedImageResourceGroupName, b.config.ManagedImageName, "")
if err == nil {
@@ -134,7 +136,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 != "" {
@@ -221,14 +223,16 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
NewStepSnapshotDataDisks(azureClient, ui, &b.config),
NewStepCaptureImage(azureClient, ui),
NewStepPublishToSharedImageGallery(azureClient, ui, &b.config),
NewStepDeleteResourceGroup(azureClient, ui),
NewStepDeleteOSDisk(azureClient, ui),
NewStepDeleteAdditionalDisks(azureClient, ui),
}
} else if b.config.OSType == constants.Target_Windows {
keyVaultDeploymentName := b.stateBag.Get(constants.ArmKeyVaultDeploymentName).(string)
steps = []multistep.Step{
NewStepCreateResourceGroup(azureClient, ui),
}
if b.config.BuildKeyVaultName == "" {
keyVaultDeploymentName := b.stateBag.Get(constants.ArmKeyVaultDeploymentName).(string)
steps = append(steps,
NewStepValidateTemplate(azureClient, ui, &b.config, GetKeyVaultDeployment),
NewStepDeployTemplate(azureClient, ui, &b.config, keyVaultDeploymentName, GetKeyVaultDeployment),
@@ -250,7 +254,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
WinRMConfig: func(multistep.StateBag) (*communicator.WinRMConfig, error) {
return &communicator.WinRMConfig{
Username: b.config.UserName,
Password: b.config.Password,
Password: b.config.Comm.WinRMPassword,
}, nil
},
},
@@ -262,6 +266,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
NewStepSnapshotDataDisks(azureClient, ui, &b.config),
NewStepCaptureImage(azureClient, ui),
NewStepPublishToSharedImageGallery(azureClient, ui, &b.config),
NewStepDeleteResourceGroup(azureClient, ui),
NewStepDeleteOSDisk(azureClient, ui),
NewStepDeleteAdditionalDisks(azureClient, ui),
)
} else {
@@ -305,7 +311,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
return NewManagedImageArtifactWithSIGAsDestination(b.config.OSType,
b.config.ManagedImageResourceGroupName,
b.config.ManagedImageName,
b.config.Location,
b.config.manageImageLocation,
managedImageID,
b.config.ManagedImageOSDiskSnapshotName,
b.config.ManagedImageDataDiskSnapshotPrefix,
@@ -315,7 +321,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
return NewManagedImageArtifact(b.config.OSType,
b.config.ManagedImageResourceGroupName,
b.config.ManagedImageName,
b.config.Location,
b.config.manageImageLocation,
managedImageID,
b.config.ManagedImageOSDiskSnapshotName,
b.config.ManagedImageDataDiskSnapshotPrefix,
@@ -393,7 +399,7 @@ func (b *Builder) configureStateBag(stateBag multistep.StateBag) {
stateBag.Put(constants.ArmComputeName, b.config.tmpComputeName)
stateBag.Put(constants.ArmDeploymentName, b.config.tmpDeploymentName)
if b.config.OSType == constants.Target_Windows && b.config.BuildKeyVaultName == "" {
if b.config.OSType == constants.Target_Windows {
stateBag.Put(constants.ArmKeyVaultDeploymentName, fmt.Sprintf("kv%s", b.config.tmpDeploymentName))
}
@@ -442,6 +448,7 @@ func (b *Builder) configureStateBag(stateBag multistep.StateBag) {
// Parameters that are only known at runtime after querying Azure.
func (b *Builder) setRuntimeParameters(stateBag multistep.StateBag) {
stateBag.Put(constants.ArmLocation, b.config.Location)
stateBag.Put(constants.ArmManagedImageLocation, b.config.manageImageLocation)
}
func (b *Builder) setTemplateParameters(stateBag multistep.StateBag) {
+25 -165
View File
@@ -18,8 +18,6 @@ import (
"strings"
"time"
"github.com/hashicorp/packer/common/random"
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute"
"github.com/Azure/go-autorest/autorest/to"
"github.com/masterzen/winrm"
@@ -29,7 +27,6 @@ import (
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/builder/azure/pkcs12"
"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/packer"
@@ -43,7 +40,6 @@ const (
DefaultUserName = "packer"
DefaultPrivateVirtualNetworkWithPublicIp = false
DefaultVMSize = "Standard_A1"
DefaultKeyVaultSKU = "standard"
)
const (
@@ -56,17 +52,15 @@ const (
// This is not an exhaustive match, but it should be extremely close.
validResourceGroupNameRe = "^[^_\\W][\\w-._\\(\\)]{0,89}$"
validManagedDiskName = "^[^_\\W][\\w-._)]{0,79}$"
validResourceNamePrefix = "^[^_\\W][\\w-._)]{0,10}$"
)
var (
reCaptureContainerName = regexp.MustCompile(`^[a-z0-9][a-z0-9\-]{2,62}$`)
reCaptureNamePrefix = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_\-\.]{0,23}$`)
reCaptureContainerName = regexp.MustCompile("^[a-z0-9][a-z0-9\\-]{2,62}$")
reCaptureNamePrefix = regexp.MustCompile("^[A-Za-z0-9][A-Za-z0-9_\\-\\.]{0,23}$")
reManagedDiskName = regexp.MustCompile(validManagedDiskName)
reResourceGroupName = regexp.MustCompile(validResourceGroupNameRe)
reSnapshotName = regexp.MustCompile(`^[A-Za-z0-9_]{1,79}$`)
reSnapshotPrefix = regexp.MustCompile(`^[A-Za-z0-9_]{1,59}$`)
reResourceNamePrefix = regexp.MustCompile(validResourceNamePrefix)
reSnapshotName = regexp.MustCompile("^[A-Za-z0-9_]{1,79}$")
reSnapshotPrefix = regexp.MustCompile("^[A-Za-z0-9_]{1,59}$")
)
type PlanInformation struct {
@@ -103,17 +97,8 @@ type Config struct {
// Authentication via OAUTH
ClientConfig client.Config `mapstructure:",squash"`
// A list of one or more fully-qualified resource IDs of user assigned
// managed identities to 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/)
@@ -191,27 +176,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
@@ -246,20 +229,16 @@ type Config struct {
// disk(s) is created with the same prefix as this value before the VM is
// captured.
ManagedImageDataDiskSnapshotPrefix string `mapstructure:"managed_image_data_disk_snapshot_prefix" required:"false"`
manageImageLocation string
// Store the image in zone-resilient storage. You need to create it in a
// 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
// [`dynamic_block`](/docs/configuration/from-1.5/expressions#dynamic-blocks)
// will allow you to create those programatically.
AzureTag hcl2template.NameValues `mapstructure:"azure_tag" required:"false"`
// Resource group under which the final artifact will be stored.
ResourceGroupName string `mapstructure:"resource_group_name"`
// Storage account under which the final artifact will be stored.
@@ -277,10 +256,7 @@ type Config struct {
BuildResourceGroupName string `mapstructure:"build_resource_group_name"`
// Specify an existing key vault to use for uploading certificates to the
// instance to connect.
BuildKeyVaultName string `mapstructure:"build_key_vault_name"`
// Specify the KeyVault SKU to create during the build. Valid values are
// standard or premium. The default value is standard.
BuildKeyVaultSKU string `mapstructure:"build_key_vault_sku"`
BuildKeyVaultName string `mapstructure:"build_key_vault_name"`
storageAccountBlobEndpoint string
// This value allows you to
// set a virtual_network_name and obtain a public IP. If this value is not
@@ -321,7 +297,7 @@ type Config struct {
//
// An example plan\_info object is defined below.
//
// ```json
// ``` json
// {
// "plan_info": {
// "plan_name": "rabbitmq",
@@ -341,12 +317,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
@@ -396,17 +370,6 @@ type Config struct {
// `virtual_network_name` is not allowed.
AllowedInboundIpAddresses []string `mapstructure:"allowed_inbound_ip_addresses"`
// Specify storage to store Boot Diagnostics -- Enabling this option
// will create 2 Files in the specified storage account. (serial console log & screehshot file)
// once the build is completed, it has to be removed manually.
// 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
// 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"`
// Runtime Values
UserName string `mapstructure-to-hcl2:",skip"`
Password string `mapstructure-to-hcl2:",skip"`
@@ -419,7 +382,6 @@ type Config struct {
tmpDeploymentName string
tmpKeyVaultName string
tmpOSDiskName string
tmpDataDiskName string
tmpSubnetName string
tmpVirtualNetworkName string
tmpNsgName string
@@ -556,17 +518,7 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
provideDefaultValues(c)
setRuntimeValues(c)
err = setUserNamePassword(c)
if err != nil {
return nil, err
}
// copy singular blocks
for _, kv := range c.AzureTag {
v := kv.Value
c.AzureTags[kv.Name] = &v
}
setUserNamePassword(c)
err = c.ClientConfig.SetDefaultValues()
if err != nil {
return nil, err
@@ -654,7 +606,7 @@ func setWinRMCertificate(c *Config) error {
}
func setRuntimeValues(c *Config) {
var tempName = NewTempName(c.CustomResourcePrefix)
var tempName = NewTempName()
c.tmpAdminPassword = tempName.AdminPassword
// store so that we can access this later during provisioning
@@ -676,54 +628,29 @@ func setRuntimeValues(c *Config) {
c.tmpNicName = tempName.NicName
c.tmpPublicIPAddressName = tempName.PublicIPAddressName
c.tmpOSDiskName = tempName.OSDiskName
c.tmpDataDiskName = tempName.DataDiskName
c.tmpSubnetName = tempName.SubnetName
c.tmpVirtualNetworkName = tempName.VirtualNetworkName
c.tmpNsgName = tempName.NsgName
c.tmpKeyVaultName = tempName.KeyVaultName
}
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
func setUserNamePassword(c *Config) {
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
return
}
if c.Comm.Type == "ssh" {
return nil
}
// WinRM comm
if c.Comm.WinRMUser == "" {
c.Comm.WinRMUser = c.UserName
}
c.UserName = c.Comm.WinRMUser
// Configure password settings using Azure generated credentials
c.Password = c.tmpAdminPassword
if c.Comm.WinRMPassword == "" {
// Configure password settings using Azure generated credentials
c.Comm.WinRMPassword = c.Password
}
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")
}
c.Password = c.Comm.WinRMPassword
return nil
}
func setCustomData(c *Config) error {
@@ -757,10 +684,6 @@ func provideDefaultValues(c *Config) {
c.ImageVersion = DefaultImageVersion
}
if c.BuildKeyVaultSKU == "" {
c.BuildKeyVaultSKU = DefaultKeyVaultSKU
}
c.ClientConfig.SetDefaultValues()
}
@@ -782,28 +705,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 {
err := fmt.Errorf("Error parsing resource ID from `user_assigned_managed_identities`; please make sure"+
" that this value follows the full resource id format: "+
"/subscriptions/<SUBSCRIPTON_ID>/resourcegroups/<RESOURCE_GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<USER_ASSIGNED_IDENTITY_NAME>.\n"+
" Original error: %s", err)
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 == "" {
@@ -996,12 +897,6 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
}
}
if c.CustomResourcePrefix != "" {
if ok, err := assertResourceNamePrefix(c.CustomResourcePrefix, "custom_resource_build_prefix"); !ok {
errs = packer.MultiErrorAppend(errs, err)
}
}
if c.VirtualNetworkName == "" && c.VirtualNetworkResourceGroupName != "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("If virtual_network_resource_group_name is specified, so must virtual_network_name"))
}
@@ -1097,13 +992,6 @@ func assertManagedImageDataDiskSnapshotName(name, setting string) (bool, error)
return true, nil
}
func assertResourceNamePrefix(name, setting string) (bool, error) {
if !isValidAzureName(reResourceNamePrefix, name) {
return false, fmt.Errorf("The setting %s must only contain characters from a-z, A-Z, 0-9 and _ and the maximum length is 10 characters", setting)
}
return true, nil
}
func assertAllowedInboundIpAddresses(ipAddresses []string, setting string) (bool, error) {
for _, ipAddress := range ipAddresses {
if net.ParseIP(ipAddress) == nil {
@@ -1128,34 +1016,6 @@ func isValidAzureName(re *regexp.Regexp, rgn string) bool {
!strings.HasSuffix(rgn, "-")
}
// The supplied password must be between 8-123 characters long and must satisfy at least 3 of password complexity requirements from the following:
// 1) Contains an uppercase character
// 2) Contains a lowercase character
// 3) Contains a numeric digit
// 4) Contains a special character
// 5) Control characters are not allowed (a very specific case - not included in this validation)
func isValidPassword(password string) bool {
if !(len(password) >= 8 && len(password) <= 123) {
return false
}
requirements := 0
if strings.ContainsAny(password, random.PossibleNumbers) {
requirements++
}
if strings.ContainsAny(password, random.PossibleLowerCase) {
requirements++
}
if strings.ContainsAny(password, random.PossibleUpperCase) {
requirements++
}
if strings.ContainsAny(password, random.PossibleSpecialCharacter) {
requirements++
}
return requirements >= 3
}
func (c *Config) validateLocationZoneResiliency(say func(s string)) {
// Docs on regions that support Availibility Zones:
// https://docs.microsoft.com/en-us/azure/availability-zones/az-overview#regions-that-support-availability-zones
+207 -232
View File
@@ -3,123 +3,110 @@ package arm
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/hcl2template"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
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"`
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"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" cty:"temporary_key_pair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `mapstructure:"ssh_public_key" cty:"ssh_public_key"`
SSHPrivateKey []byte `mapstructure:"ssh_private_key" cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
AsyncResourceGroupDelete *bool `mapstructure:"async_resourcegroup_delete" required:"false" cty:"async_resourcegroup_delete"`
}
// FlatMapstructure returns a new FlatConfig.
@@ -134,116 +121,104 @@ 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.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"cloud_environment_name": &hcldec.AttrSpec{Name: "cloud_environment_name", Type: cty.String, Required: false},
"client_id": &hcldec.AttrSpec{Name: "client_id", Type: cty.String, Required: false},
"client_secret": &hcldec.AttrSpec{Name: "client_secret", Type: cty.String, Required: false},
"client_cert_path": &hcldec.AttrSpec{Name: "client_cert_path", Type: cty.String, Required: false},
"client_jwt": &hcldec.AttrSpec{Name: "client_jwt", Type: cty.String, Required: false},
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
"subscription_id": &hcldec.AttrSpec{Name: "subscription_id", Type: cty.String, Required: false},
"capture_name_prefix": &hcldec.AttrSpec{Name: "capture_name_prefix", Type: cty.String, Required: false},
"capture_container_name": &hcldec.AttrSpec{Name: "capture_container_name", Type: cty.String, Required: false},
"shared_image_gallery": &hcldec.BlockSpec{TypeName: "shared_image_gallery", Nested: hcldec.ObjectSpec((*FlatSharedImageGallery)(nil).HCL2Spec())},
"shared_image_gallery_destination": &hcldec.BlockSpec{TypeName: "shared_image_gallery_destination", Nested: hcldec.ObjectSpec((*FlatSharedImageGalleryDestination)(nil).HCL2Spec())},
"shared_image_gallery_timeout": &hcldec.AttrSpec{Name: "shared_image_gallery_timeout", Type: cty.String, Required: false},
"shared_gallery_image_version_end_of_life_date": &hcldec.AttrSpec{Name: "shared_gallery_image_version_end_of_life_date", Type: cty.String, Required: false},
"shared_image_gallery_replica_count": &hcldec.AttrSpec{Name: "shared_image_gallery_replica_count", Type: cty.Number, Required: false},
"shared_gallery_image_version_exclude_from_latest": &hcldec.AttrSpec{Name: "shared_gallery_image_version_exclude_from_latest", Type: cty.Bool, Required: false},
"image_publisher": &hcldec.AttrSpec{Name: "image_publisher", Type: cty.String, Required: false},
"image_offer": &hcldec.AttrSpec{Name: "image_offer", Type: cty.String, Required: false},
"image_sku": &hcldec.AttrSpec{Name: "image_sku", Type: cty.String, Required: false},
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
"image_url": &hcldec.AttrSpec{Name: "image_url", Type: cty.String, Required: false},
"custom_managed_image_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.BlockAttrsSpec{TypeName: "azure_tags", ElementType: cty.String, Required: false},
"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},
"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},
"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_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 +226,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 +255,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 +286,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.
+17 -190
View File
@@ -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"
@@ -119,6 +71,22 @@ func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) {
t.Fatalf("newConfig failed: %s", err)
}
if c.Password != "override_password" {
t.Errorf("Expected 'Password' to be set to 'override_password', but found %q!", c.Password)
}
if c.Comm.SSHPassword != "override_password" {
t.Errorf("Expected 'c.Comm.SSHPassword' to be set to 'override_password', 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)
}
if c.VMSize != "override_vm_size" {
t.Errorf("Expected 'vm_size' to be set to 'override_vm_size', but found %q!", c.VMSize)
}
@@ -130,43 +98,6 @@ func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) {
if c.diskCachingType != compute.CachingTypesNone {
t.Errorf("Expected 'disk_caching_type' to be set to 'None', but found %q!", c.diskCachingType)
}
// SSH comm
if c.Password != "override_password" {
t.Errorf("Expected 'Password' to be set to 'override_password', but found %q!", c.Password)
}
if c.Comm.SSHPassword != "override_password" {
t.Errorf("Expected 'c.Comm.SSHPassword' to be set to 'override_password', 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_password"] = "Override_winrm_password1"
builderValues["winrm_username"] = "override_winrm_username"
_, err = c.Prepare(builderValues, getPackerConfiguration())
if err != nil {
t.Fatalf("newConfig failed: %s", err)
}
if c.Password != "Override_winrm_password1" {
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)
}
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 TestConfigShouldDefaultVMSizeToStandardA1(t *testing.T) {
@@ -596,10 +527,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)
}
@@ -647,7 +574,7 @@ func TestWinRMConfigShouldSetRoundTripDecorator(t *testing.T) {
config := getArmBuilderConfiguration()
config["communicator"] = "winrm"
config["winrm_username"] = "username"
config["winrm_password"] = "Password123"
config["winrm_password"] = "password"
var c Config
_, err := c.Prepare(config, getPackerConfiguration())
@@ -1993,60 +1920,6 @@ func Test_GivenZoneSupportingResiliency_ConfigValidate_ShouldNotWarn(t *testing.
}
}
func TestConfig_PrepareProvidedWinRMPassword(t *testing.T) {
config := getArmBuilderConfiguration()
config["communicator"] = "winrm"
var c Config
tc := []struct {
name string
password string
shouldFail bool
}{
{
name: "password should be longer than 8 characters",
password: "packer",
shouldFail: true,
},
{
name: "password should be shorter than 123 characters",
password: "1Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
shouldFail: true,
},
{
name: "password should have valid size but only lower and upper case letters",
password: "AAAbbbCCC",
shouldFail: true,
},
{
name: "password should have valid size but only digits and upper case letters",
password: "AAA12345",
shouldFail: true,
},
{
name: "password should have valid size, digits, upper and lower case letters",
password: "AAA12345bbb",
shouldFail: false,
},
{
name: "password should have valid size, digits, special characters and lower case letters",
password: "//12345bbb",
shouldFail: false,
},
}
for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
config["winrm_password"] = tt.password
_, err := c.Prepare(config)
fail := err != nil
if tt.shouldFail != fail {
t.Fatalf("bad: %s. Expected fail is: %t but it was %t", tt.name, tt.shouldFail, fail)
}
})
}
}
func getArmBuilderConfiguration() map[string]string {
m := make(map[string]string)
for _, v := range requiredConfigValues {
@@ -2092,49 +1965,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)
}
}
}
+1 -1
View File
@@ -77,7 +77,7 @@ func (s *StepCaptureImage) Run(ctx context.Context, state multistep.StateBag) mu
var isManagedImage = state.Get(constants.ArmIsManagedImage).(bool)
var targetManagedImageResourceGroupName = state.Get(constants.ArmManagedImageResourceGroupName).(string)
var targetManagedImageName = state.Get(constants.ArmManagedImageName).(string)
var targetManagedImageLocation = state.Get(constants.ArmLocation).(string)
var targetManagedImageLocation = state.Get(constants.ArmManagedImageLocation).(string)
s.say(fmt.Sprintf(" -> Compute ResourceGroupName : '%s'", resourceGroupName))
s.say(fmt.Sprintf(" -> Compute Name : '%s'", computeName))
@@ -131,6 +131,7 @@ func createTestStateBagStepCaptureImage() multistep.StateBag {
stateBag.Put(constants.ArmIsManagedImage, false)
stateBag.Put(constants.ArmManagedImageResourceGroupName, "")
stateBag.Put(constants.ArmManagedImageName, "")
stateBag.Put(constants.ArmManagedImageLocation, "")
stateBag.Put(constants.ArmImageParameters, &compute.Image{})
return stateBag
+20 -23
View File
@@ -111,30 +111,27 @@ func (s *StepCreateResourceGroup) Cleanup(state multistep.StateBag) {
if state.Get(constants.ArmIsExistingResourceGroup).(bool) {
ui.Say("\nThe resource group was not created by Packer, not deleting ...")
return
}
} else {
ui.Say("\nCleanup requested, deleting resource group ...")
ctx := context.TODO()
resourceGroupName := state.Get(constants.ArmResourceGroupName).(string)
if exists, err := s.exists(ctx, resourceGroupName); !exists || err != nil {
return
}
ui.Say("\nCleanup requested, deleting resource group ...")
f, err := s.client.GroupsClient.Delete(ctx, resourceGroupName)
if err == nil {
if state.Get(constants.ArmAsyncResourceGroupDelete).(bool) {
s.say(fmt.Sprintf("\n Not waiting for Resource Group delete as requested by user. Resource Group Name is %s", resourceGroupName))
} else {
err = f.WaitForCompletionRef(ctx, s.client.GroupsClient.Client)
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
ctx := context.TODO()
f, err := s.client.GroupsClient.Delete(ctx, resourceGroupName)
if err == nil {
if state.Get(constants.ArmAsyncResourceGroupDelete).(bool) {
s.say(fmt.Sprintf("\n Not waiting for Resource Group delete as requested by user. Resource Group Name is %s", resourceGroupName))
} else {
err = f.WaitForCompletionRef(ctx, s.client.GroupsClient.Client)
}
}
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resource group. Please delete it manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
return
}
if !state.Get(constants.ArmAsyncResourceGroupDelete).(bool) {
ui.Say("Resource group has been deleted.")
}
}
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resource group. Please delete it manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
return
}
if !state.Get(constants.ArmAsyncResourceGroupDelete).(bool) {
ui.Say("Resource group has been deleted.")
}
}
@@ -35,13 +35,8 @@ func NewStepDeleteAdditionalDisks(client *AzureClient, ui packer.Ui) *StepDelete
func (s *StepDeleteAdditionalDisk) deleteBlob(storageContainerName string, blobName string) error {
blob := s.client.BlobStorageClient.GetContainerReference(storageContainerName).GetBlobReference(blobName)
_, err := blob.BreakLease(nil)
if err != nil && !strings.Contains(err.Error(), "LeaseNotPresentWithLeaseOperation") {
s.say(s.client.LastError.Error())
return err
}
err := blob.Delete(nil)
err = blob.Delete(nil)
if err != nil {
s.say(s.client.LastError.Error())
}
@@ -85,26 +80,25 @@ func (s *StepDeleteAdditionalDisk) Run(ctx context.Context, state multistep.Stat
s.say("Failed to delete the managed Additional Disk!")
return processStepResult(err, s.error, state)
}
continue
}
u, err := url.Parse(additionaldisk)
if err != nil {
s.say("Failed to parse the Additional Disk's VHD URI!")
return processStepResult(err, s.error, state)
}
xs := strings.Split(u.Path, "/")
if len(xs) < 3 {
err = errors.New("Failed to parse Additional Disk's VHD URI!")
} else {
var storageAccountName = xs[1]
var blobName = strings.Join(xs[2:], "/")
u, err := url.Parse(additionaldisk)
if err != nil {
s.say("Failed to parse the Additional Disk's VHD URI!")
return processStepResult(err, s.error, state)
}
err = s.delete(storageAccountName, blobName)
}
if err != nil {
return processStepResult(err, s.error, state)
xs := strings.Split(u.Path, "/")
if len(xs) < 3 {
err = errors.New("Failed to parse Additional Disk's VHD URI!")
} else {
var storageAccountName = xs[1]
var blobName = strings.Join(xs[2:], "/")
err = s.delete(storageAccountName, blobName)
}
if err != nil {
return processStepResult(err, s.error, state)
}
}
}
return multistep.ActionContinue
+99
View File
@@ -0,0 +1,99 @@
package arm
import (
"context"
"errors"
"fmt"
"net/url"
"strings"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
type StepDeleteOSDisk struct {
client *AzureClient
delete func(string, string) error
deleteManaged func(context.Context, string, string) error
say func(message string)
error func(e error)
}
func NewStepDeleteOSDisk(client *AzureClient, ui packer.Ui) *StepDeleteOSDisk {
var step = &StepDeleteOSDisk{
client: client,
say: func(message string) { ui.Say(message) },
error: func(e error) { ui.Error(e.Error()) },
}
step.delete = step.deleteBlob
step.deleteManaged = step.deleteManagedDisk
return step
}
func (s *StepDeleteOSDisk) deleteBlob(storageContainerName string, blobName string) error {
blob := s.client.BlobStorageClient.GetContainerReference(storageContainerName).GetBlobReference(blobName)
err := blob.Delete(nil)
if err != nil {
s.say(s.client.LastError.Error())
}
return err
}
func (s *StepDeleteOSDisk) deleteManagedDisk(ctx context.Context, resourceGroupName string, imageName string) error {
xs := strings.Split(imageName, "/")
diskName := xs[len(xs)-1]
f, err := s.client.DisksClient.Delete(ctx, resourceGroupName, diskName)
if err == nil {
err = f.WaitForCompletionRef(ctx, s.client.DisksClient.Client)
}
return err
}
func (s *StepDeleteOSDisk) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
s.say("Deleting the temporary OS disk ...")
var osDisk = state.Get(constants.ArmOSDiskVhd).(string)
var isManagedDisk = state.Get(constants.ArmIsManagedImage).(bool)
var isExistingResourceGroup = state.Get(constants.ArmIsExistingResourceGroup).(bool)
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
if isManagedDisk && !isExistingResourceGroup {
s.say(fmt.Sprintf(" -> OS Disk : skipping, managed disk was used..."))
return multistep.ActionContinue
}
s.say(fmt.Sprintf(" -> OS Disk : '%s'", osDisk))
var err error
if isManagedDisk {
err = s.deleteManaged(ctx, resourceGroupName, osDisk)
if err != nil {
s.say("Failed to delete the managed OS Disk!")
return processStepResult(err, s.error, state)
}
return multistep.ActionContinue
}
u, err := url.Parse(osDisk)
if err != nil {
s.say("Failed to parse the OS Disk's VHD URI!")
return processStepResult(err, s.error, state)
}
xs := strings.Split(u.Path, "/")
if len(xs) < 3 {
err = errors.New("Failed to parse OS Disk's VHD URI!")
} else {
var storageAccountName = xs[1]
var blobName = strings.Join(xs[2:], "/")
err = s.delete(storageAccountName, blobName)
}
return processStepResult(err, s.error, state)
}
func (*StepDeleteOSDisk) Cleanup(multistep.StateBag) {
}
@@ -0,0 +1,227 @@
package arm
import (
"context"
"errors"
"fmt"
"testing"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/helper/multistep"
)
func TestStepDeleteOSDiskShouldFailIfGetFails(t *testing.T) {
var testSubject = &StepDeleteOSDisk{
delete: func(string, string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
deleteManaged: func(context.Context, string, string) error { return nil },
say: func(message string) {},
error: func(e error) {},
}
stateBag := DeleteTestStateBagStepDeleteOSDisk("http://storage.blob.core.windows.net/images/pkrvm_os.vhd")
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionHalt {
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
}
if _, ok := stateBag.GetOk(constants.Error); ok == false {
t.Fatalf("Expected the step to set stateBag['%s'], but it was not.", constants.Error)
}
}
func TestStepDeleteOSDiskShouldPassIfGetPasses(t *testing.T) {
var testSubject = &StepDeleteOSDisk{
delete: func(string, string) error { return nil },
say: func(message string) {},
error: func(e error) {},
}
stateBag := DeleteTestStateBagStepDeleteOSDisk("http://storage.blob.core.windows.net/images/pkrvm_os.vhd")
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionContinue {
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
}
if _, ok := stateBag.GetOk(constants.Error); ok == true {
t.Fatalf("Expected the step to not set stateBag['%s'], but it was.", constants.Error)
}
}
func TestStepDeleteOSDiskShouldTakeStepArgumentsFromStateBag(t *testing.T) {
var actualStorageContainerName string
var actualBlobName string
var testSubject = &StepDeleteOSDisk{
delete: func(storageContainerName string, blobName string) error {
actualStorageContainerName = storageContainerName
actualBlobName = blobName
return nil
},
say: func(message string) {},
error: func(e error) {},
}
stateBag := DeleteTestStateBagStepDeleteOSDisk("http://storage.blob.core.windows.net/images/pkrvm_os.vhd")
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionContinue {
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
}
if actualStorageContainerName != "images" {
t.Fatalf("Expected the storage container name to be 'images', but found '%s'.", actualStorageContainerName)
}
if actualBlobName != "pkrvm_os.vhd" {
t.Fatalf("Expected the blob name to be 'pkrvm_os.vhd', but found '%s'.", actualBlobName)
}
}
func TestStepDeleteOSDiskShouldHandleComplexStorageContainerNames(t *testing.T) {
var actualStorageContainerName string
var actualBlobName string
var testSubject = &StepDeleteOSDisk{
delete: func(storageContainerName string, blobName string) error {
actualStorageContainerName = storageContainerName
actualBlobName = blobName
return nil
},
say: func(message string) {},
error: func(e error) {},
}
stateBag := DeleteTestStateBagStepDeleteOSDisk("http://storage.blob.core.windows.net/abc/def/pkrvm_os.vhd")
testSubject.Run(context.Background(), stateBag)
if actualStorageContainerName != "abc" {
t.Fatalf("Expected the storage container name to be 'abc/def', but found '%s'.", actualStorageContainerName)
}
if actualBlobName != "def/pkrvm_os.vhd" {
t.Fatalf("Expected the blob name to be 'pkrvm_os.vhd', but found '%s'.", actualBlobName)
}
}
func TestStepDeleteOSDiskShouldFailIfVHDNameCannotBeURLParsed(t *testing.T) {
var testSubject = &StepDeleteOSDisk{
delete: func(string, string) error { return nil },
say: func(message string) {},
error: func(e error) {},
deleteManaged: func(context.Context, string, string) error { return nil },
}
// Invalid URL per https://golang.org/src/net/url/url_test.go
stateBag := DeleteTestStateBagStepDeleteOSDisk("http://[fe80::1%en0]/")
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionHalt {
t.Fatalf("Expected the step to return 'ActionHalt', but got '%v'.", result)
}
if _, ok := stateBag.GetOk(constants.Error); ok == false {
t.Fatalf("Expected the step to not stateBag['%s'], but it was.", constants.Error)
}
}
func TestStepDeleteOSDiskShouldFailIfVHDNameIsTooShort(t *testing.T) {
var testSubject = &StepDeleteOSDisk{
delete: func(string, string) error { return nil },
say: func(message string) {},
error: func(e error) {},
deleteManaged: func(context.Context, string, string) error { return nil },
}
stateBag := DeleteTestStateBagStepDeleteOSDisk("storage.blob.core.windows.net/abc")
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionHalt {
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
}
if _, ok := stateBag.GetOk(constants.Error); ok == false {
t.Fatalf("Expected the step to not stateBag['%s'], but it was.", constants.Error)
}
}
func TestStepDeleteOSDiskShouldPassIfManagedDiskInTempResourceGroup(t *testing.T) {
var testSubject = &StepDeleteOSDisk{
delete: func(string, string) error { return nil },
say: func(message string) {},
error: func(e error) {},
}
stateBag := new(multistep.BasicStateBag)
stateBag.Put(constants.ArmOSDiskVhd, "subscriptions/123-456-789/resourceGroups/existingresourcegroup/providers/Microsoft.Compute/disks/osdisk")
stateBag.Put(constants.ArmIsManagedImage, true)
stateBag.Put(constants.ArmIsExistingResourceGroup, false)
stateBag.Put(constants.ArmResourceGroupName, "testgroup")
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionContinue {
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
}
if _, ok := stateBag.GetOk(constants.Error); ok == true {
t.Fatalf("Expected the step to not set stateBag['%s'], but it was.", constants.Error)
}
}
func TestStepDeleteOSDiskShouldFailIfManagedDiskInExistingResourceGroupFailsToDelete(t *testing.T) {
var testSubject = &StepDeleteOSDisk{
delete: func(string, string) error { return nil },
say: func(message string) {},
error: func(e error) {},
deleteManaged: func(context.Context, string, string) error { return errors.New("UNIT TEST FAIL!") },
}
stateBag := new(multistep.BasicStateBag)
stateBag.Put(constants.ArmOSDiskVhd, "subscriptions/123-456-789/resourceGroups/existingresourcegroup/providers/Microsoft.Compute/disks/osdisk")
stateBag.Put(constants.ArmIsManagedImage, true)
stateBag.Put(constants.ArmIsExistingResourceGroup, true)
stateBag.Put(constants.ArmResourceGroupName, "testgroup")
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionHalt {
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
}
if _, ok := stateBag.GetOk(constants.Error); ok == false {
t.Fatalf("Expected the step to not stateBag['%s'], but it was.", constants.Error)
}
}
func TestStepDeleteOSDiskShouldFailIfManagedDiskInExistingResourceGroupIsDeleted(t *testing.T) {
var testSubject = &StepDeleteOSDisk{
delete: func(string, string) error { return nil },
say: func(message string) {},
error: func(e error) {},
deleteManaged: func(context.Context, string, string) error { return nil },
}
stateBag := new(multistep.BasicStateBag)
stateBag.Put(constants.ArmOSDiskVhd, "subscriptions/123-456-789/resourceGroups/existingresourcegroup/providers/Microsoft.Compute/disks/osdisk")
stateBag.Put(constants.ArmIsManagedImage, true)
stateBag.Put(constants.ArmIsExistingResourceGroup, true)
stateBag.Put(constants.ArmResourceGroupName, "testgroup")
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionContinue {
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
}
if _, ok := stateBag.GetOk(constants.Error); ok == true {
t.Fatalf("Expected the step to not set stateBag['%s'], but it was.", constants.Error)
}
}
func DeleteTestStateBagStepDeleteOSDisk(osDiskVhd string) multistep.StateBag {
stateBag := new(multistep.BasicStateBag)
stateBag.Put(constants.ArmOSDiskVhd, osDiskVhd)
stateBag.Put(constants.ArmIsManagedImage, false)
stateBag.Put(constants.ArmIsExistingResourceGroup, false)
stateBag.Put(constants.ArmResourceGroupName, "testgroup")
return stateBag
}
@@ -0,0 +1,152 @@
package arm
import (
"context"
"fmt"
"time"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
const (
maxResourcesToDelete = 50
)
type StepDeleteResourceGroup struct {
client *AzureClient
delete func(ctx context.Context, state multistep.StateBag, resourceGroupName string) error
say func(message string)
error func(e error)
}
func NewStepDeleteResourceGroup(client *AzureClient, ui packer.Ui) *StepDeleteResourceGroup {
var step = &StepDeleteResourceGroup{
client: client,
say: func(message string) { ui.Say(message) },
error: func(e error) { ui.Error(e.Error()) },
}
step.delete = step.deleteResourceGroup
return step
}
func (s *StepDeleteResourceGroup) deleteResourceGroup(ctx context.Context, state multistep.StateBag, resourceGroupName string) error {
var err error
if state.Get(constants.ArmIsExistingResourceGroup).(bool) {
s.say("\nThe resource group was not created by Packer, only deleting individual resources ...")
var deploymentName = state.Get(constants.ArmDeploymentName).(string)
err = s.deleteDeploymentResources(ctx, deploymentName, resourceGroupName)
if err != nil {
return err
}
if keyVaultDeploymentName, ok := state.GetOk(constants.ArmKeyVaultDeploymentName); ok {
// Only delete if custom keyvault was not provided.
if exists := state.Get(constants.ArmIsExistingKeyVault).(bool); exists {
err = s.deleteDeploymentResources(ctx, keyVaultDeploymentName.(string), resourceGroupName)
if err != nil {
return err
}
}
}
return nil
} else {
s.say("\nThe resource group was created by Packer, deleting ...")
f, err := s.client.GroupsClient.Delete(ctx, resourceGroupName)
if err == nil {
if state.Get(constants.ArmAsyncResourceGroupDelete).(bool) {
// No need to wait for the completion for delete if request is Accepted
s.say(fmt.Sprintf("\nResource Group is being deleted, not waiting for deletion due to config. Resource Group Name '%s'", resourceGroupName))
} else {
f.WaitForCompletionRef(ctx, s.client.GroupsClient.Client)
}
}
if err != nil {
s.say(s.client.LastError.Error())
}
return err
}
}
func (s *StepDeleteResourceGroup) deleteDeploymentResources(ctx context.Context, deploymentName, resourceGroupName string) error {
maxResources := int32(maxResourcesToDelete)
deploymentOperations, err := s.client.DeploymentOperationsClient.ListComplete(ctx, resourceGroupName, deploymentName, &maxResources)
if err != nil {
s.reportIfError(err, resourceGroupName)
return err
}
for deploymentOperations.NotDone() {
deploymentOperation := deploymentOperations.Value()
// Sometimes an empty operation is added to the list by Azure
if deploymentOperation.Properties.TargetResource == nil {
deploymentOperations.Next()
continue
}
resourceName := *deploymentOperation.Properties.TargetResource.ResourceName
resourceType := *deploymentOperation.Properties.TargetResource.ResourceType
s.say(fmt.Sprintf(" -> %s : '%s'",
resourceType,
resourceName))
retry.Config{
Tries: 10,
RetryDelay: (&retry.Backoff{InitialBackoff: 10 * time.Second, MaxBackoff: 600 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
err := deleteResource(ctx, s.client,
resourceType,
resourceName,
resourceGroupName)
if err != nil {
s.reportIfError(err, resourceName)
}
return nil
})
if err = deploymentOperations.Next(); err != nil {
return err
}
}
return nil
}
func (s *StepDeleteResourceGroup) reportIfError(err error, resourceName string) {
if err != nil {
s.say(fmt.Sprintf("Error deleting resource. Please delete manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceName, err.Error()))
s.error(err)
}
}
func (s *StepDeleteResourceGroup) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
s.say("Deleting resource group ...")
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
s.say(fmt.Sprintf(" -> ResourceGroupName : '%s'", resourceGroupName))
err := s.delete(ctx, state, resourceGroupName)
if err != nil {
state.Put(constants.Error, err)
s.error(err)
return multistep.ActionHalt
}
state.Put(constants.ArmIsResourceGroupCreated, false)
return multistep.ActionContinue
}
func (*StepDeleteResourceGroup) Cleanup(multistep.StateBag) {
}
@@ -0,0 +1,78 @@
package arm
import (
"context"
"fmt"
"testing"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/helper/multistep"
)
func TestStepDeleteResourceGroupShouldFailIfDeleteFails(t *testing.T) {
var testSubject = &StepDeleteResourceGroup{
delete: func(context.Context, multistep.StateBag, string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
say: func(message string) {},
error: func(e error) {},
}
stateBag := DeleteTestStateBagStepDeleteResourceGroup()
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionHalt {
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
}
if _, ok := stateBag.GetOk(constants.Error); ok == false {
t.Fatalf("Expected the step to set stateBag['%s'], but it was not.", constants.Error)
}
}
func TestStepDeleteResourceGroupShouldPassIfDeletePasses(t *testing.T) {
var testSubject = &StepDeleteResourceGroup{
delete: func(context.Context, multistep.StateBag, string) error { return nil },
say: func(message string) {},
error: func(e error) {},
}
stateBag := DeleteTestStateBagStepDeleteResourceGroup()
var result = testSubject.Run(context.Background(), stateBag)
if result != multistep.ActionContinue {
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
}
if _, ok := stateBag.GetOk(constants.Error); ok == true {
t.Fatalf("Expected the step to not set stateBag['%s'], but it was.", constants.Error)
}
}
func TestStepDeleteResourceGroupShouldDeleteStateBagArmResourceGroupCreated(t *testing.T) {
var testSubject = &StepDeleteResourceGroup{
delete: func(context.Context, multistep.StateBag, string) error {
return nil
},
say: func(message string) {},
error: func(e error) {},
}
stateBag := DeleteTestStateBagStepDeleteResourceGroup()
testSubject.Run(context.Background(), stateBag)
value, ok := stateBag.GetOk(constants.ArmIsResourceGroupCreated)
if !ok {
t.Fatal("Expected the resource bag value arm.IsResourceGroupCreated to exist")
}
if value.(bool) {
t.Fatalf("Expected arm.IsResourceGroupCreated to be false, but got %q", value)
}
}
func DeleteTestStateBagStepDeleteResourceGroup() multistep.StateBag {
stateBag := new(multistep.BasicStateBag)
stateBag.Put(constants.ArmResourceGroupName, "Unit Test: ResourceGroupName")
stateBag.Put(constants.ArmIsResourceGroupCreated, "Unit Test: IsResourceGroupCreated")
return stateBag
}
+97 -120
View File
@@ -42,109 +42,6 @@ func NewStepDeployTemplate(client *AzureClient, ui packer.Ui, config *Config, de
return step
}
func (s *StepDeployTemplate) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
s.say("Deploying deployment template ...")
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
s.say(fmt.Sprintf(" -> ResourceGroupName : '%s'", resourceGroupName))
s.say(fmt.Sprintf(" -> DeploymentName : '%s'", s.name))
return processStepResult(
s.deploy(ctx, resourceGroupName, s.name),
s.error, state)
}
func (s *StepDeployTemplate) Cleanup(state multistep.StateBag) {
defer func() {
err := s.deleteTemplate(context.Background(), state)
if err != nil {
s.say(s.client.LastError.Error())
}
}()
//Only clean up if this was an existing resource group and the resource group
//is marked as created
existingResourceGroup := state.Get(constants.ArmIsExistingResourceGroup).(bool)
resourceGroupCreated := state.Get(constants.ArmIsResourceGroupCreated).(bool)
if !existingResourceGroup || !resourceGroupCreated {
return
}
ui := state.Get("ui").(packer.Ui)
ui.Say("\nThe resource group was not created by Packer, deleting individual resources ...")
deploymentName := s.name
resourceGroupName := state.Get(constants.ArmResourceGroupName).(string)
// Get image disk details before deleting the image; otherwise we won't be able to
// delete the disk as the image request will return a 404
computeName := state.Get(constants.ArmComputeName).(string)
imageType, imageName, err := s.disk(context.TODO(), resourceGroupName, computeName)
if err != nil && !strings.Contains(err.Error(), "ResourceNotFound") {
ui.Error(fmt.Sprintf("Could not retrieve OS Image details: %s", err))
}
ui.Say(" -> Deployment Resources within: " + deploymentName)
if deploymentName != "" {
maxResources := int32(50)
deploymentOperations, err := s.client.DeploymentOperationsClient.ListComplete(context.TODO(), resourceGroupName, deploymentName, &maxResources)
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resources. Please delete them manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
}
for deploymentOperations.NotDone() {
deploymentOperation := deploymentOperations.Value()
// Sometimes an empty operation is added to the list by Azure
if deploymentOperation.Properties.TargetResource == nil {
if err := deploymentOperations.Next(); err != nil {
ui.Error(fmt.Sprintf("Error moving to to next deployment operation ...\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
break
}
continue
}
ui.Say(fmt.Sprintf(" -> %s : '%s'",
*deploymentOperation.Properties.TargetResource.ResourceType,
*deploymentOperation.Properties.TargetResource.ResourceName))
err = s.delete(context.TODO(), s.client,
*deploymentOperation.Properties.TargetResource.ResourceType,
*deploymentOperation.Properties.TargetResource.ResourceName,
resourceGroupName)
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resource. Please delete manually.\n\n"+
"Name: %s\n"+
"Error: %s", *deploymentOperation.Properties.TargetResource.ResourceName, err))
}
if err = deploymentOperations.Next(); err != nil {
ui.Error(fmt.Sprintf("Error deleting resources. Please delete them manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
break
}
}
// The disk is not defined as an operation in the template so it has to be deleted separately
if imageType == "" && imageName == "" {
return
}
ui.Say(fmt.Sprintf(" -> %s : '%s'", imageType, imageName))
err = s.deleteDisk(context.TODO(), imageType, imageName, resourceGroupName)
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resource. Please delete manually.\n\n"+
"Name: %s\n"+
"Error: %s", imageName, err))
}
}
}
func (s *StepDeployTemplate) deployTemplate(ctx context.Context, resourceGroupName string, deploymentName string) error {
deployment, err := s.factory(s.config)
if err != nil {
@@ -165,32 +62,48 @@ func (s *StepDeployTemplate) deleteTemplate(ctx context.Context, state multistep
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
var deploymentName = s.name
ui := state.Get("ui").(packer.Ui)
ui.Say(fmt.Sprintf("Removing the created Deployment object: '%s'", deploymentName))
f, err := s.client.DeploymentsClient.Delete(ctx, resourceGroupName, deploymentName)
if err == nil {
err = f.WaitForCompletionRef(ctx, s.client.DeploymentsClient.Client)
}
if err != nil {
s.say(s.client.LastError.Error())
}
return err
}
func (s *StepDeployTemplate) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
s.say("Deploying deployment template ...")
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
s.say(fmt.Sprintf(" -> ResourceGroupName : '%s'", resourceGroupName))
s.say(fmt.Sprintf(" -> DeploymentName : '%s'", s.name))
return processStepResult(
s.deploy(ctx, resourceGroupName, s.name),
s.error, state)
}
func (s *StepDeployTemplate) getImageDetails(ctx context.Context, resourceGroupName string, computeName string) (string, string, error) {
//We can't depend on constants.ArmOSDiskVhd being set
var imageName, imageType string
var imageName string
var imageType string
vm, err := s.client.VirtualMachinesClient.Get(ctx, resourceGroupName, computeName, "")
if err != nil {
return imageName, imageType, err
}
if vm.StorageProfile.OsDisk.Vhd != nil {
imageType = "image"
imageName = *vm.StorageProfile.OsDisk.Vhd.URI
} else {
imageType = "Microsoft.Compute/disks"
imageName = *vm.StorageProfile.OsDisk.ManagedDisk.ID
if vm.StorageProfile.OsDisk.Vhd != nil {
imageType = "image"
imageName = *vm.StorageProfile.OsDisk.Vhd.URI
} else {
imageType = "Microsoft.Compute/disks"
imageName = *vm.StorageProfile.OsDisk.ManagedDisk.ID
}
}
return imageType, imageName, nil
}
@@ -204,7 +117,8 @@ func deleteResource(ctx context.Context, client *AzureClient, resourceType strin
}
return err
case "Microsoft.KeyVault/vaults":
_, err := client.VaultClientDelete.Delete(ctx, resourceGroupName, resourceName)
// TODO(paulmey): not sure why VaultClient doesn't do cancellation
_, err := client.VaultClientDelete.Delete(resourceGroupName, resourceName)
return err
case "Microsoft.Network/networkInterfaces":
f, err := client.InterfacesClient.Delete(ctx, resourceGroupName, resourceName)
@@ -245,7 +159,6 @@ func (s *StepDeployTemplate) deleteImage(ctx context.Context, imageType string,
}
return err
}
// VHD image
u, err := url.Parse(imageName)
if err != nil {
@@ -259,11 +172,75 @@ func (s *StepDeployTemplate) deleteImage(ctx context.Context, imageType string,
var blobName = strings.Join(xs[2:], "/")
blob := s.client.BlobStorageClient.GetContainerReference(storageAccountName).GetBlobReference(blobName)
_, err = blob.BreakLease(nil)
if err != nil && !strings.Contains(err.Error(), "LeaseNotPresentWithLeaseOperation") {
s.say(s.client.LastError.Error())
return err
err = blob.Delete(nil)
return err
}
func (s *StepDeployTemplate) Cleanup(state multistep.StateBag) {
defer s.deleteTemplate(context.Background(), state)
//Only clean up if this was an existing resource group and the resource group
//is marked as created
var existingResourceGroup = state.Get(constants.ArmIsExistingResourceGroup).(bool)
var resourceGroupCreated = state.Get(constants.ArmIsResourceGroupCreated).(bool)
if !existingResourceGroup || !resourceGroupCreated {
return
}
ui := state.Get("ui").(packer.Ui)
ui.Say("\nThe resource group was not created by Packer, deleting individual resources ...")
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
var computeName = state.Get(constants.ArmComputeName).(string)
var deploymentName = s.name
imageType, imageName, err := s.disk(context.TODO(), resourceGroupName, computeName)
if err != nil {
ui.Error("Could not retrieve OS Image details")
}
return blob.Delete(nil)
ui.Say(" -> Deployment Resources within: " + deploymentName)
if deploymentName != "" {
maxResources := int32(50)
deploymentOperations, err := s.client.DeploymentOperationsClient.ListComplete(context.TODO(), resourceGroupName, deploymentName, &maxResources)
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resources. Please delete them manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
}
for deploymentOperations.NotDone() {
deploymentOperation := deploymentOperations.Value()
// Sometimes an empty operation is added to the list by Azure
if deploymentOperation.Properties.TargetResource == nil {
deploymentOperations.Next()
continue
}
ui.Say(fmt.Sprintf(" -> %s : '%s'",
*deploymentOperation.Properties.TargetResource.ResourceType,
*deploymentOperation.Properties.TargetResource.ResourceName))
err = s.delete(context.TODO(), s.client,
*deploymentOperation.Properties.TargetResource.ResourceType,
*deploymentOperation.Properties.TargetResource.ResourceName,
resourceGroupName)
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resource. Please delete manually.\n\n"+
"Name: %s\n"+
"Error: %s", *deploymentOperation.Properties.TargetResource.ResourceName, err))
}
if err = deploymentOperations.Next(); err != nil {
ui.Error(fmt.Sprintf("Error deleting resources. Please delete them manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
break
}
}
// The disk is not defined as an operation in the template so has to be
// deleted separately
ui.Say(fmt.Sprintf(" -> %s : '%s'", imageType, imageName))
err = s.deleteDisk(context.TODO(), imageType, imageName, resourceGroupName)
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resource. Please delete manually.\n\n"+
"Name: %s\n"+
"Error: %s", imageName, err))
}
}
}
@@ -131,15 +131,15 @@ func (s *StepPublishToSharedImageGallery) Run(ctx context.Context, stateBag mult
miSigReplicaCount = constants.SharedImageGalleryImageVersionDefaultMaxReplicaCount
}
s.say(fmt.Sprintf(" -> MDI ID used for SIG publish : '%s'", mdiID))
s.say(fmt.Sprintf(" -> SIG publish resource group : '%s'", miSigPubRg))
s.say(fmt.Sprintf(" -> SIG gallery name : '%s'", miSIGalleryName))
s.say(fmt.Sprintf(" -> SIG image name : '%s'", miSGImageName))
s.say(fmt.Sprintf(" -> SIG image version : '%s'", miSGImageVersion))
s.say(fmt.Sprintf(" -> SIG replication regions : '%v'", miSigReplicationRegions))
s.say(fmt.Sprintf(" -> SIG image version endoflife date : '%s'", miSGImageVersionEndOfLifeDate))
s.say(fmt.Sprintf(" -> SIG image version exclude from latest : '%t'", miSGImageVersionExcludeFromLatest))
s.say(fmt.Sprintf(" -> SIG replica count [1, 10] : '%d'", miSigReplicaCount))
s.say(fmt.Sprintf(" -> MDI ID used for SIG publish : '%s'", mdiID))
s.say(fmt.Sprintf(" -> SIG publish resource group : '%s'", miSigPubRg))
s.say(fmt.Sprintf(" -> SIG gallery name : '%s'", miSIGalleryName))
s.say(fmt.Sprintf(" -> SIG image name : '%s'", miSGImageName))
s.say(fmt.Sprintf(" -> SIG image version : '%s'", miSGImageVersion))
s.say(fmt.Sprintf(" -> SIG replication regions : '%v'", miSigReplicationRegions))
s.say(fmt.Sprintf(" -> SIG image version endoflife date : '%s'", miSGImageVersionEndOfLifeDate))
s.say(fmt.Sprintf(" -> SIG image version exclude from latest : '%t'", miSGImageVersionExcludeFromLatest))
s.say(fmt.Sprintf(" -> SIG replica count [1, 10] : '%d'", miSigReplicaCount))
createdGalleryImageVersionID, err := s.publish(ctx, mdiID, miSigPubRg, miSIGalleryName, miSGImageName, miSGImageVersion, miSigReplicationRegions, miSGImageVersionEndOfLifeDate, miSGImageVersionExcludeFromLatest, miSigReplicaCount, location, tags)
+14 -69
View File
@@ -17,7 +17,6 @@ type templateFactoryFunc func(*Config) (*resources.Deployment, error)
func GetKeyVaultDeployment(config *Config) (*resources.Deployment, error) {
params := &template.TemplateParameters{
KeyVaultName: &template.TemplateParameter{Value: config.tmpKeyVaultName},
KeyVaultSKU: &template.TemplateParameter{Value: config.BuildKeyVaultSKU},
KeyVaultSecretValue: &template.TemplateParameter{Value: config.winrmCertificate},
ObjectId: &template.TemplateParameter{Value: config.ClientConfig.ObjectID},
TenantId: &template.TemplateParameter{Value: config.ClientConfig.TenantID},
@@ -37,7 +36,6 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error)
DnsNameForPublicIP: &template.TemplateParameter{Value: config.tmpComputeName},
NicName: &template.TemplateParameter{Value: config.tmpNicName},
OSDiskName: &template.TemplateParameter{Value: config.tmpOSDiskName},
DataDiskName: &template.TemplateParameter{Value: config.tmpDataDiskName},
PublicIPAddressName: &template.TemplateParameter{Value: config.tmpPublicIPAddressName},
SubnetName: &template.TemplateParameter{Value: config.tmpSubnetName},
StorageAccountBlobEndpoint: &template.TemplateParameter{Value: config.storageAccountBlobEndpoint},
@@ -55,34 +53,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 +84,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
}
isManaged := config.CustomManagedImageName != "" || (config.ManagedImageName != "" && config.ImagePublisher != "")
builder.SetAdditionalDisks(config.AdditionalDiskSize, 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 {
@@ -169,18 +125,7 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error)
}
}
if config.BootDiagSTGAccount != "" {
err = builder.SetBootDiagnostics(config.BootDiagSTGAccount)
if err != nil {
return nil, err
}
}
err = builder.SetTags(&config.AzureTags)
if err != nil {
return nil, err
}
builder.SetTags(&config.AzureTags)
doc, _ := builder.ToJSON()
return createDeploymentParameters(*doc, params)
}
@@ -5,9 +5,6 @@
"keyVaultName": {
"type": "string"
},
"keyVaultSKU": {
"type": "string"
},
"keyVaultSecretValue": {
"type": "securestring"
},
@@ -42,7 +39,7 @@
"enabledForTemplateDeployment": "true",
"sku": {
"family": "A",
"name": "[parameters('keyVaultSKU')]"
"name": "standard"
},
"tenantId": "[parameters('tenantId')]"
},
@@ -8,9 +8,6 @@
"adminUsername": {
"type": "string"
},
"dataDiskName": {
"type": "string"
},
"dnsNameForPublicIP": {
"type": "string"
},
@@ -149,10 +146,10 @@
]
},
"osProfile": {
"adminPassword": "[parameters('adminPassword')]",
"adminUsername": "[parameters('adminUsername')]",
"computerName": "[parameters('vmName')]",
"linuxConfiguration": {
"disablePasswordAuthentication": true,
"ssh": {
"publicKeys": [
{
@@ -8,9 +8,6 @@
"adminUsername": {
"type": "string"
},
"dataDiskName": {
"type": "string"
},
"dnsNameForPublicIP": {
"type": "string"
},
@@ -153,10 +150,10 @@
]
},
"osProfile": {
"adminPassword": "[parameters('adminPassword')]",
"adminUsername": "[parameters('adminUsername')]",
"computerName": "[parameters('vmName')]",
"linuxConfiguration": {
"disablePasswordAuthentication": true,
"ssh": {
"publicKeys": [
{
@@ -8,9 +8,6 @@
"adminUsername": {
"type": "string"
},
"dataDiskName": {
"type": "string"
},
"dnsNameForPublicIP": {
"type": "string"
},

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