Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e564b4883 |
+49
-78
@@ -1,17 +1,14 @@
|
||||
orbs:
|
||||
win: circleci/windows@1.0.0
|
||||
codecov: codecov/codecov@1.0.5
|
||||
|
||||
version: 2.1
|
||||
|
||||
executors:
|
||||
golang:
|
||||
docker:
|
||||
- image: docker.mirror.hashicorp.services/circleci/golang:1.15
|
||||
resource_class: medium+
|
||||
- image: circleci/golang:1.13
|
||||
darwin:
|
||||
macos:
|
||||
xcode: "12.0.0"
|
||||
xcode: "9.0"
|
||||
|
||||
commands:
|
||||
install-go-run-tests-unix:
|
||||
@@ -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
|
||||
@@ -67,27 +61,14 @@ jobs:
|
||||
steps:
|
||||
- install-go-run-tests-unix:
|
||||
GOOS: darwin
|
||||
GOVERSION: "1.15"
|
||||
- codecov/upload:
|
||||
file: coverage.txt
|
||||
GOVERSION: "1.13"
|
||||
test-windows:
|
||||
executor:
|
||||
name: win/vs2019
|
||||
shell: bash.exe
|
||||
steps:
|
||||
- install-go-run-tests-windows:
|
||||
GOVERSION: "1.15"
|
||||
- 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
|
||||
GOVERSION: "1.13"
|
||||
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: docker.mirror.hashicorp.services/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 login -u $WEBSITE_DOCKER_USER -p $WEBSITE_DOCKER_PASS
|
||||
docker build -t hashicorp/packer-website:$IMAGE_TAG .
|
||||
docker tag hashicorp/packer-website:$IMAGE_TAG hashicorp/packer-website:latest
|
||||
docker push hashicorp/packer-website
|
||||
fi
|
||||
algolia-index:
|
||||
docker:
|
||||
- image: docker.mirror.hashicorp.services/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
|
||||
|
||||
@@ -1,18 +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 and mocks
|
||||
- "**/*.hcl2spec.go"
|
||||
- "**/*_mock.go"
|
||||
@@ -3,10 +3,8 @@
|
||||
*.sh text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.mdx text eol=lf
|
||||
*.ps1 text eol=lf
|
||||
*.hcl text eol=lf
|
||||
*.txt text eol=lf
|
||||
go.mod text eol=lf
|
||||
go.sum text eol=lf
|
||||
common/test-fixtures/root/* eol=lf
|
||||
|
||||
+36
-324
@@ -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
|
||||
|
||||
@@ -259,8 +249,8 @@ does not attempt to track the latest version for each dependency.
|
||||
#### Code generation
|
||||
|
||||
Packer relies on `go generate` to generate a [peg parser for boot
|
||||
commands](https://github.com/hashicorp/packer/blob/master/packer-plugin-sdk/bootcommand/boot_command.go),
|
||||
[docs](https://github.com/hashicorp/packer/blob/master/website/pages/partials/builder/amazon/chroot/_Config-not-required.mdx)
|
||||
commands](https://github.com/hashicorp/packer/blob/master/common/bootcommand/boot_command.go),
|
||||
[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
|
||||
@@ -301,15 +289,15 @@ You can run tests for individual packages using commands like this:
|
||||
make test TEST=./builder/amazon/...
|
||||
```
|
||||
|
||||
#### Running Builder Acceptance Tests
|
||||
#### Running Acceptance Tests
|
||||
|
||||
Packer has [acceptance tests](https://en.wikipedia.org/wiki/Acceptance_testing)
|
||||
for various builders. These typically require an API key (AWS, GCE), or
|
||||
additional software to be installed on your computer (VirtualBox, VMware).
|
||||
|
||||
If you're working on a new builder or builder feature and want to verify it is
|
||||
functioning (and also hasn't broken anything else), we recommend creating or
|
||||
running the acceptance tests.
|
||||
functioning (and also hasn't broken anything else), we recommend running the
|
||||
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
|
||||
@@ -340,282 +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 Provisioner 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 the
|
||||
**ACC_TEST_BUILDERS** environment variable to tell the tests which 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 go test ./provisioner/shell/... -v -timeout=1h
|
||||
```
|
||||
- Do the same but using the Makefile
|
||||
```
|
||||
ACC_TEST_BUILDERS=amazon-ebs make provisioners-acctest TEST=./provisioner/shell
|
||||
```
|
||||
- Run all provisioner acceptance tests against the Amazon EBS builder.
|
||||
```
|
||||
ACC_TEST_BUILDERS=amazon-ebs make provisioners-acctest TEST=./...
|
||||
```
|
||||
- Run all provisioner acceptance tests against all builders whenever they are compatible.
|
||||
```
|
||||
ACC_TEST_BUILDERS=all make provisioners-acctest TEST=./...
|
||||
```
|
||||
|
||||
The **ACC_TEST_BUILDERS** env variable accepts a list of builders separated by
|
||||
commas. (e.g. `ACC_TEST_BUILDERS=amazon-ebs,virtualbox-iso`)
|
||||
|
||||
|
||||
#### Writing Provisioner Acceptance Tests
|
||||
|
||||
Packer has implemented a `ProvisionerTestCase` structure to help write
|
||||
provisioner acceptance tests.
|
||||
|
||||
```go
|
||||
type ProvisionerTestCase struct {
|
||||
// Check is called after this step is executed in order to test that
|
||||
// the step executed successfully. If this is not set, then the next
|
||||
// step will be called
|
||||
Check func(*exec.Cmd, string) error
|
||||
// IsCompatible checks whether a provisioner is able to run against a
|
||||
// given builder type and guest operating system, and returns a boolean.
|
||||
// if it returns true, the test combination is okay to run. If false, the
|
||||
// test combination is not okay to run.
|
||||
IsCompatible func(builderType string, BuilderGuestOS string) bool
|
||||
// Name is the name of the test case. Be simple but unique and descriptive.
|
||||
Name string
|
||||
// Setup, if non-nil, will be called once before the test case
|
||||
// runs. This can be used for some setup like setting environment
|
||||
// variables, or for validation prior to the
|
||||
// test running. For example, you can use this to make sure certain
|
||||
// binaries are installed, or text fixtures are in place.
|
||||
Setup func() error
|
||||
// Teardown will be called before the test case is over regardless
|
||||
// of if the test succeeded or failed. This should return an error
|
||||
// in the case that the test can't guarantee all resources were
|
||||
// properly cleaned up.
|
||||
Teardown builderT.TestTeardownFunc
|
||||
// Template is the provisioner template to use.
|
||||
// The provisioner template fragment must be a json-formatted string
|
||||
// containing the provisioner definition but no other portions of a packer
|
||||
// template. For
|
||||
// example:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "type": "shell-local",
|
||||
// "inline", ["echo hello world"]
|
||||
// }
|
||||
//```
|
||||
//
|
||||
// is a valid entry for "template" here, but the complete Packer template:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "provisioners": [
|
||||
// {
|
||||
// "type": "shell-local",
|
||||
// "inline", ["echo hello world"]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// is invalid as input.
|
||||
//
|
||||
// You may provide multiple provisioners in the same template. For example:
|
||||
// ```json
|
||||
// {
|
||||
// "type": "shell-local",
|
||||
// "inline", ["echo hello world"]
|
||||
// },
|
||||
// {
|
||||
// "type": "shell-local",
|
||||
// "inline", ["echo hello world 2"]
|
||||
// }
|
||||
// ```
|
||||
Template string
|
||||
// Type is the type of provisioner.
|
||||
Type string
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
To start writing a new provisioner acceptance test, you should add a test file
|
||||
named `provisioner_acc_test.go` in the same folder as your provisioner is
|
||||
defined. Create a test case by implementing the above struct, and run it
|
||||
by calling `provisioneracc.TestProvisionersAgainstBuilders(testCase, t)`
|
||||
|
||||
The following example has been adapted from a shell-local provisioner test:
|
||||
|
||||
```
|
||||
import (
|
||||
"github.com/hashicorp/packer-plugin-sdk/acctest/provisioneracc"
|
||||
"github.com/hashicorp/packer-plugin-sdk/acctest/testutils"
|
||||
)
|
||||
|
||||
// ...
|
||||
|
||||
func TestAccShellProvisioner_basic(t *testing.T) {
|
||||
// Create a json template fragment containing just the provisioners you want
|
||||
// to run.
|
||||
templateString := `{
|
||||
"type": "shell-local",
|
||||
"script": "test-fixtures/script.sh",
|
||||
"max_retries" : 5
|
||||
}`
|
||||
|
||||
// instantiate a test case.
|
||||
testCase := &provisioneracc.ProvisionerTestCase{
|
||||
IsCompatible: func() bool {return true},
|
||||
Name: "shell-local-provisioner-basic",
|
||||
Teardown: func() error {
|
||||
testutils.CleanupFiles("test-fixtures/file.txt")
|
||||
return nil
|
||||
},
|
||||
Template: templateString,
|
||||
Type: "shell-local",
|
||||
Check: func(buildcommand *exec.Cmd, logfile string) error {
|
||||
if buildcommand.ProcessState != nil {
|
||||
if buildcommand.ProcessState.ExitCode() != 0 {
|
||||
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
|
||||
}
|
||||
}
|
||||
filecontents, err := loadFile("file.txt")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !strings.Contains(filecontents, "hello") {
|
||||
return fmt.Errorf("file contents were wrong: %s", filecontents)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
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)
|
||||
}
|
||||
```
|
||||
|
||||
The method `TestProvisionersAgainstBuilders` will run the provisioner against
|
||||
all available and compatible builders. If there are not builders compatible with
|
||||
the test you want to run, you can add a builder using the following steps:
|
||||
|
||||
Create a subdirectory in provisioneracc/test-fixtures for the type of builder
|
||||
you are adding. In this subdirectory, add one json file containing a single
|
||||
builder fragment. For example, one of our amazon-ebs builders is defined in
|
||||
provisioneracc/test-fixtures/amazon-ebs/amazon-ebs.txt and contains:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "amazon-ebs",
|
||||
"ami_name": "packer-acc-test",
|
||||
"instance_type": "t2.micro",
|
||||
"region": "us-east-1",
|
||||
"ssh_username": "ubuntu",
|
||||
"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
|
||||
},
|
||||
"force_deregister" : true,
|
||||
"tags": {
|
||||
"packer-test": "true"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
note that this fragment does not contain anything other than a single builder
|
||||
definition. The testing framework will combine this with the provisioner
|
||||
fragment to create a working json template.
|
||||
|
||||
In order to tell the testing framework how to use this builder fragment, you
|
||||
need to implement a `BuilderFixture` struct:
|
||||
|
||||
```go
|
||||
type BuilderFixture struct {
|
||||
// Name is the name of the builder fixture.
|
||||
// Be simple and descriptive.
|
||||
Name string
|
||||
// Setup creates necessary extra test fixtures, and renders their values
|
||||
// into the BuilderFixture.Template.
|
||||
Setup func()
|
||||
// Template is the path to a builder template fragment.
|
||||
// The builder template fragment must be a json-formatted file containing
|
||||
// the builder definition but no other portions of a packer template. For
|
||||
// example:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "type": "null",
|
||||
// "communicator", "none"
|
||||
// }
|
||||
//```
|
||||
//
|
||||
// is a valid entry for "template" here, but the complete Packer template:
|
||||
//
|
||||
// ```json
|
||||
// {
|
||||
// "builders": [
|
||||
// "type": "null",
|
||||
// "communicator": "none"
|
||||
// ]
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// is invalid as input.
|
||||
//
|
||||
// Only provide one builder template fragment per file.
|
||||
TemplatePath string
|
||||
|
||||
// GuestOS says what guest os type the builder template fragment creates.
|
||||
// Valid values are "windows", "linux" or "darwin" guests.
|
||||
GuestOS string
|
||||
|
||||
// HostOS says what host os type the builder is capable of running on.
|
||||
// Valid values are "any", windows", or "posix". If you set "posix", then
|
||||
// this builder can run on a "linux" or "darwin" platform. If you set
|
||||
// "any", then this builder can be used on any platform.
|
||||
HostOS string
|
||||
|
||||
Teardown builderT.TestTeardownFunc
|
||||
}
|
||||
```
|
||||
Implement this struct to the file "provisioneracc/builders.go", then add
|
||||
the new implementation to the `BuildersAccTest` map in
|
||||
`provisioneracc/provisioners.go`
|
||||
|
||||
Once you finish these steps, you should be ready to run your new provisioner
|
||||
acceptance test by setting the name used in the BuildersAccTest map as your
|
||||
`ACC_TEST_BUILDERS` environment variable.
|
||||
|
||||
#### Debugging Plugins
|
||||
|
||||
Each packer plugin runs in a separate process and communicates via RPC over a
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,37 +0,0 @@
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'website/**'
|
||||
|
||||
name: Check markdown links on modified website files
|
||||
jobs:
|
||||
vercel-deployment-poll:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 3 #cancel job if no deployment is found within x minutes
|
||||
outputs:
|
||||
url: ${{ steps.waitForVercelPreviewDeployment.outputs.url }}
|
||||
steps:
|
||||
- name: Wait for Vercel preview deployment to be ready
|
||||
uses: nywilken/wait-for-vercel-preview@master
|
||||
id: waitForVercelPreviewDeployment
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
max_timeout: 600 # in seconds, set really high to leverage job timeout-minutes values
|
||||
allow_inactive: true # needed to ensure we get a URL for a previously released deployment
|
||||
markdown-link-check:
|
||||
needs: vercel-deployment-poll
|
||||
if: ${{ needs.vercel-deployment-poll.outputs.url != '' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get Deployment URL
|
||||
run:
|
||||
echo "DEPLOYMENT_URL=${{ needs.vercel-deployment-poll.outputs.url }}" >> $GITHUB_ENV
|
||||
- name: Checkout source branch
|
||||
uses: actions/checkout@master
|
||||
- name: Check links
|
||||
uses: gaurav-nelson/github-action-markdown-link-check@v1
|
||||
with:
|
||||
use-quiet-mode: 'yes'
|
||||
file-extension: 'mdx'
|
||||
check-modified-files-only: 'yes'
|
||||
folder-path: 'website/content'
|
||||
@@ -1,17 +0,0 @@
|
||||
on:
|
||||
schedule:
|
||||
- cron: "45 0 * * *"
|
||||
name: Check Markdown links on main branch
|
||||
jobs:
|
||||
markdown-link-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set deployment URL env
|
||||
run:
|
||||
echo "DEPLOYMENT_URL=https://packer-git-master.hashicorp.vercel.app" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@master
|
||||
- uses: gaurav-nelson/github-action-markdown-link-check@v1
|
||||
with:
|
||||
use-quiet-mode: 'yes'
|
||||
file-extension: 'mdx'
|
||||
folder-path: 'website/content'
|
||||
@@ -27,4 +27,3 @@ Thumbs.db
|
||||
/packer.exe
|
||||
.project
|
||||
cache
|
||||
/.vscode/
|
||||
|
||||
@@ -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
@@ -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
-790
@@ -1,785 +1,11 @@
|
||||
## 1.7.0 (Upcoming)
|
||||
|
||||
## 1.6.6 (December 16, 2020)
|
||||
|
||||
### FEATURES:
|
||||
* **New command** `fmt` allows users to format existing HCL2 configuration
|
||||
files into a canonical style. Please see [fmt command
|
||||
docs](https://packer.io/docs/commands/fmt) for more details. [GH-10225]
|
||||
[GH-10377]
|
||||
* **New function** `env` allows users to set the default value of a variable to
|
||||
the value of an environment variable. Please see [env function
|
||||
docs](https://www.packer.io/docs/templates/hcl_templates/functions/contextual/env") for
|
||||
more details. [GH-10240]
|
||||
* **Future Scaffolding** This release contains a large number of no-op
|
||||
refactoring changes. The Packer team at HashiCorp is preparing to split the
|
||||
plugins and core to make it easier for our third party maintainers and
|
||||
community members to release and maintain plugins, just like HashiCorp did
|
||||
with the Terraform Core-Provider split. The Packer team is committed to
|
||||
making sure that this split is seamless for our users and for our community
|
||||
maintainers -- if you are a community maintainer, you may want to follow
|
||||
along with some of the work by looking at the
|
||||
[core-plugin-split github tag.](https://github.com/hashicorp/packer/pulls?q=is%3Apr+label%3Acore-plugin-split)
|
||||
No one needs to do anything, yet, but we felt it was worth calling out all
|
||||
the work that isn't making it into the changelog. We will be following up
|
||||
with lots of documentation and communication in early 2021 with more
|
||||
information.
|
||||
|
||||
### IMPROVEMENTS
|
||||
* builder/amazon-ebs: Add tags to launch templates. [GH-10203]
|
||||
* builder/amazon: Add support for Amazon EBS gp3 volumes. [Gh-10338]
|
||||
* builder/amazon: Increase default max_retries to lessen throttling issues.
|
||||
[GH-10290]
|
||||
* builder/amazon: Support AWS gp3 volumes [GH-10338]
|
||||
* builder/amazon: Support root volume encryption for amazon-chroot. [GH-10243]
|
||||
* builder/amazon: Validate IOPS ratio. [GH-10199]
|
||||
* builder/azure-arm: Add Azure CLI authentication support to builder.
|
||||
[GH-10157]
|
||||
* builder/azure-arm: Create keyvaults with SoftDelete enabled. [GH-10210]
|
||||
* builder/digitalocean: New option to provision with private ip. [GH-10093]
|
||||
* builder/google: Add `wait_to_add_ssh_keys` option to delay the addition of
|
||||
SSH configuration that may be disrupted during an instance boot sequence.
|
||||
[GH-10320]
|
||||
* builder/google: Add support for creating shielded VMs. [GH-10172]
|
||||
* builder/googlecompute-export: Add logging.write to service account scopes.
|
||||
[GH-10316]
|
||||
* builder/oracle-oci: Support image launch mode. [GH-10212]
|
||||
* builder/outscale: Add outscale.hk endpoint support [GH-10207]
|
||||
* builder/outscale: Add x509 certificate support. [GH-10161]
|
||||
* builder/proxmox: New config option for boot-order. [GH-10260]
|
||||
* builder/scaleway: Use the SDK functions to load profile from file and env.
|
||||
[GH-10181]
|
||||
* builder/virtualbox: Allow attaching guest additions with "none" communicator.
|
||||
[GH-10306]
|
||||
* builder/vmware: Make compatible with MacOS BigSur by using Apple DHCP leases
|
||||
instead of VMWare leases [GH-10384]
|
||||
* builder/vsphere: New option to add additional storage to a cloned vm.
|
||||
[GH-10287]
|
||||
* builder/yandex: More resilient image mounting and initialization. [GH-10335]
|
||||
* builder/yandex: Update user-data to not use cloud-config fields to prevent
|
||||
possible user data collisions. [GH-10385]
|
||||
* core/hcl: Update to `hcl2_upgrade` command to support complex variable values
|
||||
and packer version blocks. [GH-10221]
|
||||
* hcl2upgrade: Update command to fix `env` call upgrade. [GH-10244]
|
||||
* post-processor/vagrant-cloud: Add support for uploading directly to storage
|
||||
on Vagrant Cloud. [GH-10193]
|
||||
* post-processor/yandex-export: Add retries and wait after disk attach
|
||||
operation. [GH-10303]
|
||||
* post-processor/yandex-export: Show progress on export. [GH-10368]
|
||||
* post-processor/yandex-export: Use ssh communicator in export. [GH-10352]
|
||||
* post-processor/yandex-export: Verify the access to a specific bucket.
|
||||
[GH-10188]
|
||||
* provisioner/salt-masterless: Call winrepo.update_git_repos and
|
||||
pkg.refresh_db. [GH-10201]
|
||||
|
||||
### BUG FIXES
|
||||
* builder/amazon: Fix retry logic in AWS spot instance tagging. [GH-10394]
|
||||
* builder/amazon: Fix single `tag` interpolation to allow for templating engine
|
||||
usage. [GH-10224]
|
||||
* builder/google: Fix crash when using the `-on-error` build flag. [GH-10247]
|
||||
* builder/google: Fix issue with service account detection when running Packer
|
||||
on a compute instance with `use_os_login` enabled. [GH-10360]
|
||||
* builder/qemu: Fix duplication of main disk when setting "disk_image: true".
|
||||
[GH-10337]
|
||||
* builder/qemu: Fix nil pointer dereference when loading values from state.
|
||||
[GH-10249]
|
||||
* builder/qemu: Fix panic when disk_image=true and source image has no file
|
||||
extension. [GH-10226]
|
||||
* builder/vagrant: Return error if ssh-config command fails. [GH-10213]
|
||||
* builder/vsphere: WaitForIP should not return an error if an IP is not found
|
||||
[GH-10321]
|
||||
* builder/yandex: Change disk creation method to manual. [GH-10250]
|
||||
* builder/yandex: Fix issue with UserAgent string. [GH-10361]
|
||||
* builder/yandex: Fixed using cloud config when using IPv6. [GH-10297]
|
||||
* core/hcl: Ensure the `reverse` function does not break when given a value of
|
||||
type list. [GH-10380]
|
||||
* post-processor/yandex-export: Check service account id. [GH-10305]
|
||||
|
||||
## 1.6.5 (October 30, 2020)
|
||||
|
||||
### FEATURES:
|
||||
* New Builder(s): Proxmox builder has been split into two new builders
|
||||
`proxmox-iso` and `promox-clone`. See [Proxmox
|
||||
Builder](https://packer.io/docs/builders/proxmox) for more information on
|
||||
the builder. For users of the previous `proxmox` builder please use `packer
|
||||
fix` to migrate your templates to the new `promox-iso` builder. [GH-9262]
|
||||
|
||||
### BUG FIXES:
|
||||
|
||||
* builder/amazon: SSM connection now recovers from reboots. [GH-10003]
|
||||
* builder/azure-arm: Fix build failures due to the deletion of additional
|
||||
managed disks defined in "disk_additional_size". [GH-10163]
|
||||
* builder/azure-chroot: Fix typo in option `exlude_from_latest` to
|
||||
`exclude_from_latest`. Old name will still be respected. [GH-10034]
|
||||
* builder/googlecompute: Fix HCL image_encryption_key fields and use the same
|
||||
casing in JSON and HCL2 [GH-10173]
|
||||
* builder/openstack: Fix source image validation regression when using filters.
|
||||
[GH-10065]
|
||||
* builder/proxmox: Fix unhandled buildvar type for HCL2 enabled build
|
||||
templates. [GH-10154]
|
||||
* builder/qemu: Fix a regression where Packer would not wait properly in
|
||||
step_shutdown when a null communicator was used. [GH-10178]
|
||||
* builder/qemu: Fix crash in step_run of qemu when loading commhostport form
|
||||
the statebag in a situation where the communicator is none. [GH-10145]
|
||||
* builder/vsphere-clone: Packer was not respecting the "destroy" flag set in
|
||||
the content library config, and always keeping the source vm. This has been
|
||||
fixed. [GH-10165]
|
||||
* builder/vsphere: Ensure builds are able to continue when no communicator has
|
||||
been specified `"communicator": "none"`. [GH-9964]
|
||||
* builder/vsphere: Fix CD uploads so that Packer does not try to delete a CD
|
||||
that was not successfully uploaded. [GH-10155]
|
||||
* core/hcl: Hide sensitive variables from output. [GH-10031]
|
||||
* core/hcl: Packer HCL's "Coalesce" function now behaves same way as
|
||||
Terraform's. [GH-10016]
|
||||
* core: Fix artifact handling so that input artifacts are properly preserved in
|
||||
postprocessors that don't modify artifacts. [GH-9996]
|
||||
* core: Fix pathing in cd_files to copy proper directory tree when user
|
||||
provided absolute paths. [GH-10022]
|
||||
* provisioner/ansible: Ansible galaxy no longer forces use of collections in v1
|
||||
files. [GH-10010]
|
||||
## 1.5.5 (Upcoming)
|
||||
|
||||
### IMPROVEMENTS:
|
||||
|
||||
* builder/amazon-ebssurrogate: Apply snapshot tags at snapshot creation time.
|
||||
[GH-10150]
|
||||
* builder/amazon: Add `io2` as a supported volume type. [GH-10102]
|
||||
* builder/amazon: Add support for source instance tenancy [GH-10085]
|
||||
* builder/google: Add service account impersonation. [GH-9968] [GH-10054]
|
||||
* builder/googlecompute: Add `skip_create_image` option. [GH-10115]
|
||||
* builder/googlecompute: Allow users to select the algorithm to use when
|
||||
generating temporary SSH keypair [GH-10111]
|
||||
* builder/linode: Add `state_timeout` attribute to Linode builder. [GH-10128]
|
||||
* builder/oracle-oci: New option to specify image compartment separate from
|
||||
build compartment. [GH-10040]
|
||||
* builder/oracle-oci: New option to specify boot volume size. [GH-10017]
|
||||
* builder/oracle: Add `base_image_filter` option as alternative to
|
||||
`base_image_ocid` [GH-10116]
|
||||
* builder/outscale: Migrate to new Outscale SDK. [GH-10056]
|
||||
* builder/proxmox: split Proxmox into proxmox-iso and proxmox-clone. [GH-9626]
|
||||
[GH-10166]
|
||||
* builder/scaleway: Allow the user to use an image label (eg ubuntu_focal)
|
||||
instead of a hardcoded UUID on the Scaleway builder. [GH-10061]
|
||||
* builder/vsphere: Skip iso download if hashed file is already present on
|
||||
remote datastore. [GH-10143]
|
||||
* builder/yandex: Add support for IAM credentials in the token field and
|
||||
YC_TOKEN environment variable. [GH-10158]
|
||||
* core/hcl: Add ability to set version restrictions [GH-10149]
|
||||
* core/hcl: Add build.name variable so users can access build name in addition
|
||||
to source name. [GH-10114]
|
||||
* core/hcl: Add consul_key function to HCL templates. [GH-10119]
|
||||
* core/hcl: Add HCL2 aws_secretsmanager function [GH-10124]
|
||||
* core/hcl: Add packer.version variable to hcl configs so users can access the
|
||||
Packer release version. [GH-10117]
|
||||
* core: Let user provide type of generated ssh key instead of always doing ssh-
|
||||
rsa [GH-10101]
|
||||
|
||||
## 1.6.4 (September 30, 2020)
|
||||
|
||||
### BUG FIXES:
|
||||
* builder/amazon: Fix authentication issue when using instance profiles or
|
||||
assumed roles for loading session-derived credentials. [GH-10007]
|
||||
* builder/azure: Fix crash when using `azure_tag` or `azure_tags` configuration
|
||||
options. [GH-10014]
|
||||
* builder/qemu: Ensure `qemu_img_args` are honored during the disk convert
|
||||
step. [GH-10001]
|
||||
|
||||
## 1.6.3 (September 25, 2020)
|
||||
|
||||
### IMPROVEMENTS:
|
||||
* builder/amazon: Add `pause_before_ssm` option to pause for some time before
|
||||
establishing a Session Manager session; defaults to 10s. [GH-9988]
|
||||
* builder/amazon: Implement assume_role option that matches Terraform behavior.
|
||||
[GH-9981]
|
||||
* builder/azure: Support publishing to a Shared Image Gallery with a different
|
||||
subscription id [GH-9875]
|
||||
* builder/openstack: Add `external_source_image_url` and
|
||||
`external_source_image_format` to support building images from external
|
||||
source URLs. [GH-9992]
|
||||
* builder/openstack: Include API requests and responses as part of the debug
|
||||
log output. [GH-9972]
|
||||
* builder/oracle-oci: Add `create_vnic_details` option for launch details.
|
||||
[GH-9856]
|
||||
* builder/oracle-oci: Allow freeform and defined tags to be added to an instance.
|
||||
[GH-9802]
|
||||
* builder/proxmox: Add `io_thread` option for supporting io threads when using
|
||||
a `virtio-scsi-single` controller with a `scsi` or `virtio` disk type.
|
||||
[GH-9969]
|
||||
* builder/proxmox: Add ability to specify interfaces for http_directory and VM.
|
||||
[GH-9874]
|
||||
* builder/proxmox: Allow the mounting of multiple ISOs via the `cd_drive`
|
||||
option. [GH-9653]
|
||||
* builder/proxmox: Fix boot command special keys. [GH-9885]
|
||||
* builder/qemu: Add `qemu_img_args` option to set special cli flags for calls
|
||||
to qemu-img [GH-9956]
|
||||
* builder/qemu: Add `skip_resize_disk` option to skip the resizing of QCOW2
|
||||
images. [GH-9896] [GH-9860]
|
||||
* builder/qemu: Skip qemu-img convert on MacOS to prevent the creation of
|
||||
corrupt images [QEMU
|
||||
#1776920](https://bugs.launchpad.net/qemu/+bug/1776920) [GH-9949]
|
||||
* builder/scaleway: Change default boottype to local. [GH-9853]
|
||||
* builder/scaleway: Update scaleway to use non-deprecated sdk. [GH-9902]
|
||||
* builder/vmware: Add `vnc_over_websocket` to allow the sending of a
|
||||
`boot_command` to hosts running ESXi 6.7 and above. [GH-9938]
|
||||
* builder/vmware: Allow user to set vmware tools source path. [GH-9983]
|
||||
* builder/vsphere-clone: Add ability to set `mac_address` [GH-9930]
|
||||
* builder/vsphere-clone: Add floppy_files, cd_files, and iso_paths options.
|
||||
[GH-9963]
|
||||
* builder/vsphere-iso: Add NVMe controller support. [GH-9880]
|
||||
* builder/vsphere: Look for a default resource pool when root resource pool is
|
||||
not found. [GH-9809]
|
||||
* core: Add support for running cygwin/msys2 based cd/iso creation tool
|
||||
[GH-9954]
|
||||
* core: New `cd_files` option to mount iso for modern OSes which don't support
|
||||
floppies. [GH-9796] [GH-9919] [GH-9928] [GH-9932] [GH-9941]
|
||||
* HCL2: When the type of a variable is not known evaluate setting as a literal
|
||||
string instead of a variable name. [GH-9863]
|
||||
* post-processor/vagrant: Support the use of template variables within
|
||||
Vagrantfile templates. [GH-9923]
|
||||
* post-processor/yandex-import: Allow custom API endpoint. [GH-9850]
|
||||
* provisioner/ansible: Add support for Ansible Galaxy Collections. [GH-9903]
|
||||
|
||||
### BUG FIXES:
|
||||
* builder/amazon-ebs: Fix issue where retrying on invalid IAM instance profile
|
||||
error was creating multiple spot instances. [GH-9946]
|
||||
* builder/amazon-ebssurrogate: Fix issue where builder defaults to AWS managed
|
||||
key even when custom `kms_key_id` is set. [GH-9959]
|
||||
* builder/amazon: Update ssm_driver log polling logic to prevent infinite loops
|
||||
when SSM driver is terminated outside of Packer. [GH-9991]
|
||||
* builder/azure: Fix crash when using HCL2 configs. [GH-9984] [GH-9985]
|
||||
* builder/qemu: Fix hardcoded lowerbound causing negative ports [GH-9905]
|
||||
* builder/qemu: Skip compaction when backing file is used. [GH-9918]
|
||||
* builder/scaleway: Add pre validate step to prevent the creation of multiple
|
||||
images with the same name. [GH-9840]
|
||||
* builder/vmware-iso: Prevent the use of reserved SCSI ID 0:7 when attaching
|
||||
multiple disks. [GH-9940]
|
||||
* builder/vsphere: Fix overly strict iso_path validation regex. [GH-9855]
|
||||
* command/console: Prevent failure when there are unknown vars. [GH-9864]
|
||||
* command/inspect: Allow unset variables in HCL2 and JSON. [GH-9832]
|
||||
* core: Prevent the UI progressbar from hanging and crashing when there is no
|
||||
TTY available. [GH-9974]
|
||||
* core: Use $APPDATA over $HOME on Windows hosts when determining homedir.
|
||||
[GH-9830]
|
||||
* post-processor/digitalocean-import: Fix crash caused by empty artifact.Files
|
||||
slice. [GH-9857]
|
||||
* post-processor/yandex-export: Check for error after runner completes.
|
||||
[GH-9925]
|
||||
* post-processor/yandex-export: Set metadata key to expected value on error.
|
||||
[GH-9849]
|
||||
* post-processor/yandex-import: Fix S3 URL construct process. [GH-9931]
|
||||
|
||||
## 1.6.2 (August 28, 2020)
|
||||
|
||||
### FEATURES:
|
||||
* **New command** `hcl2_upgrade` is a JSON to HCL2 transpiler that allows users
|
||||
to transform an existing JSON configuration template into its HCL2 template
|
||||
equivalent. Please see [hcl2_upgrade command
|
||||
docs](https://packer.io/docs/commands/hcl2_upgrade) for more details.
|
||||
[GH-9659]
|
||||
|
||||
### 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-vmx: Add additional disk configuration option. Previously
|
||||
only implemented for vmware-iso builder [GH-9815]
|
||||
* 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 option to export to ovf or ova from a local vmware build
|
||||
[GH-9825]
|
||||
* builder/vmware: Add progress tracker to vmware-esx5 iso upload. [GH-9779]
|
||||
* builder/vsphere-iso: Add support for building on a single ESXi host
|
||||
[GH-9793]
|
||||
* 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]
|
||||
* builder/vsphere: Update `iso_paths` to support reading ISOs from Content
|
||||
Library paths [GH-9801]
|
||||
* 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/ansible-remote: Add `ansible_ssh_extra_args` so users can specify
|
||||
extra arguments to pass to ssh [GH-9821]
|
||||
* 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/amazon: Add retry logic to the spot instance creation step to handle
|
||||
"Invalid IAM Instance Profile name" errors [GH-9810]
|
||||
* builder/amazon: Update the `aws_secretsmanager` function to read from the AWS
|
||||
credentials file for obtaining default region information; fixes the
|
||||
'MissingRegion' error when AWS_REGION is not set [GH-9781]
|
||||
* 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]
|
||||
* post-processor/yandex-export: Fix issue when validating region_name [GH-9814]
|
||||
* provisioner/inspec: Fix the 'Unsupported argument; An argument named
|
||||
"command"' error when using the inspec provisioner in an HCL2 configuration
|
||||
[GH-9800]
|
||||
|
||||
## 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
|
||||
@@ -935,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]
|
||||
@@ -1029,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]
|
||||
@@ -1059,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]
|
||||
@@ -1092,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]
|
||||
@@ -1107,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)
|
||||
|
||||
@@ -1243,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]
|
||||
@@ -1487,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]
|
||||
@@ -1665,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)
|
||||
|
||||
@@ -1738,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]
|
||||
@@ -1759,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:
|
||||
@@ -1901,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]
|
||||
@@ -4022,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]
|
||||
|
||||
+23
-43
@@ -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/ @scaleway/devtools
|
||||
/website/pages/docs/builders/scaleway* @scaleway/devtools
|
||||
/builder/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
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM docker.mirror.hashicorp.services/ubuntu:16.04
|
||||
FROM ubuntu:16.04
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
TEST?=$(shell go list ./...)
|
||||
COUNT?=1
|
||||
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)
|
||||
@@ -18,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 dev
|
||||
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
|
||||
|
||||
@@ -57,14 +51,14 @@ install-gen-deps: ## Install dependencies for code generation
|
||||
# out code dependencies; so a go mod tidy will remove them again. `go
|
||||
# install` seems to install the last tagged version and we want to install
|
||||
# master.
|
||||
@(cd $(TEMPDIR) && GO111MODULE=on go get github.com/mna/pigeon@master)
|
||||
@(cd $(TEMPDIR) && GO111MODULE=on go get github.com/alvaroloes/enumer@master)
|
||||
@go install ./cmd/struct-markdown
|
||||
@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 \
|
||||
@@ -88,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 ./...
|
||||
@@ -111,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,11 +115,13 @@ fmt-examples:
|
||||
# generate runs `go generate` to build the dynamically generated
|
||||
# source files.
|
||||
generate: install-gen-deps ## Generate dynamically generated code
|
||||
@echo "==> removing autogenerated markdown..." # but don't remove partials generated in the SDK and copied over.
|
||||
@find website/pages -path website/pages/partials/packer-plugin-sdk -prune -o -type f | xargs grep -l '^<!-- Code generated' | xargs rm -f
|
||||
@echo "==> removing autogenerated markdown..."
|
||||
@find website/source/ -type f | xargs grep -l '^<!-- Code generated' | xargs rm
|
||||
@echo "==> removing autogenerated code..."
|
||||
@find post-processor helper builder provisioner -type f | xargs grep -l '^// Code generated' | xargs rm -f
|
||||
PROJECT_ROOT="$(shell pwd)" go generate $(shell go list ./... | grep -v packer-plugin-sdk)
|
||||
@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 fmt command/plugin.go
|
||||
|
||||
generate-check: generate ## Check go code generation is on par
|
||||
@echo "==> Checking that auto-generated code is not changed..."
|
||||
@@ -135,25 +132,15 @@ generate-check: generate ## Check go code generation is on par
|
||||
fi
|
||||
|
||||
test: mode-check vet ## Run unit tests
|
||||
@go test -count $(COUNT) $(TEST) $(TESTARGS) -timeout=3m
|
||||
|
||||
# acctest runs provisioners acceptance tests
|
||||
provisioners-acctest: #install-build-deps generate
|
||||
ACC_TEST_BUILDERS=$(ACC_TEST_BUILDERS) go test $(TEST) $(TESTARGS) -timeout=1h
|
||||
@go test $(TEST) $(TESTARGS) -timeout=3m
|
||||
|
||||
# testacc runs acceptance tests
|
||||
testacc: # install-build-deps generate ## Run 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."
|
||||
PACKER_ACC=1 go test -count $(COUNT) -v $(TEST) $(TESTARGS) -timeout=120m
|
||||
PACKER_ACC=1 go test -v $(TEST) $(TESTARGS) -timeout=45m
|
||||
|
||||
testrace: mode-check vet ## Test with race detection enabled
|
||||
@GO111MODULE=off go test -count $(COUNT) -race $(TEST) $(TESTARGS) -timeout=3m -p=8
|
||||
|
||||
# Runs code coverage and open a html page with report
|
||||
cover:
|
||||
go test -count $(COUNT) $(TEST) $(TESTARGS) -timeout=3m -coverprofile=coverage.out
|
||||
go tool cover -html=coverage.out
|
||||
rm coverage.out
|
||||
@GO111MODULE=off go test -race $(TEST) $(TESTARGS) -timeout=3m -p=8
|
||||
|
||||
check-vendor-vs-mod: ## Check that go modules and vendored code are on par
|
||||
@GO111MODULE=on go mod vendor
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
# Packer
|
||||
|
||||
[![Build Status][circleci-badge]][circleci]
|
||||
[![Build Status][travis-badge]][travis]
|
||||
[![Windows Build Status][appveyor-badge]][appveyor]
|
||||
[](https://pkg.go.dev/github.com/hashicorp/packer)
|
||||
[![GoDoc][godoc-badge]][godoc]
|
||||
[![GoReportCard][report-badge]][report]
|
||||
[](https://codecov.io/gh/hashicorp/packer)
|
||||
|
||||
[circleci-badge]: https://circleci.com/gh/hashicorp/packer.svg?style=svg
|
||||
[circleci]: https://app.circleci.com/pipelines/github/hashicorp/packer
|
||||
[travis-badge]: https://travis-ci.org/hashicorp/packer.svg?branch=master
|
||||
[travis]: https://travis-ci.org/hashicorp/packer
|
||||
[appveyor-badge]: https://ci.appveyor.com/api/projects/status/miavlgnp989e5obc/branch/master?svg=true
|
||||
[appveyor]: https://ci.appveyor.com/project/hashicorp/packer
|
||||
[godoc-badge]: https://godoc.org/github.com/hashicorp/packer?status.svg
|
||||
@@ -25,7 +24,7 @@ from a single source configuration.
|
||||
Packer is lightweight, runs on every major operating system, and is highly
|
||||
performant, creating machine images for multiple platforms in parallel. Packer
|
||||
comes out of the box with support for many platforms, the full list of which can
|
||||
be found at https://www.packer.io/docs/builders.
|
||||
be found at https://www.packer.io/docs/builders/index.html.
|
||||
|
||||
Support for other platforms can be added via plugins.
|
||||
|
||||
@@ -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/).
|
||||
|
||||
@@ -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
|
||||
@@ -11,33 +11,33 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer/builder/alicloud/version"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/hashicorp/packer/version"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
// 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`.
|
||||
@@ -78,7 +78,7 @@ func (c *AlicloudAccessConfig) Client() (*ClientWrapper, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.AppendUserAgent(Packer, version.AlicloudPluginVersion.FormattedVersion())
|
||||
client.AppendUserAgent(Packer, version.FormattedVersion())
|
||||
client.SetReadTimeout(DefaultRequestReadTimeout)
|
||||
c.client = &ClientWrapper{client}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type Artifact struct {
|
||||
@@ -136,7 +136,7 @@ func (a *Artifact) Destroy() error {
|
||||
if len(errors) == 1 {
|
||||
return errors[0]
|
||||
} else {
|
||||
return &packersdk.MultiError{Errors: errors}
|
||||
return &packer.MultiError{Errors: errors}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func TestArtifact_Impl(t *testing.T) {
|
||||
var _ packersdk.Artifact = new(Artifact)
|
||||
var _ packer.Artifact = new(Artifact)
|
||||
}
|
||||
|
||||
func TestArtifactId(t *testing.T) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//go:generate mapstructure-to-hcl2 -type Config,AlicloudDiskDevice
|
||||
|
||||
// The alicloud contains a packersdk.Builder implementation that
|
||||
// The alicloud contains a packer.Builder implementation that
|
||||
// builds ecs images for alicloud.
|
||||
package ecs
|
||||
|
||||
@@ -9,13 +9,12 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// The unique ID for this builder
|
||||
@@ -47,7 +46,6 @@ func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstruct
|
||||
|
||||
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
err := config.Decode(&b.config, &config.DecodeOpts{
|
||||
PluginType: BuilderId,
|
||||
Interpolate: true,
|
||||
InterpolateContext: &b.config.ctx,
|
||||
InterpolateFilter: &interpolate.RenderFilter{
|
||||
@@ -67,20 +65,20 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
}
|
||||
|
||||
// Accumulate any errors
|
||||
var errs *packersdk.MultiError
|
||||
errs = packersdk.MultiErrorAppend(errs, b.config.AlicloudAccessConfig.Prepare(&b.config.ctx)...)
|
||||
errs = packersdk.MultiErrorAppend(errs, b.config.AlicloudImageConfig.Prepare(&b.config.ctx)...)
|
||||
errs = packersdk.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...)
|
||||
var errs *packer.MultiError
|
||||
errs = packer.MultiErrorAppend(errs, b.config.AlicloudAccessConfig.Prepare(&b.config.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, b.config.AlicloudImageConfig.Prepare(&b.config.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...)
|
||||
|
||||
if errs != nil && len(errs.Errors) > 0 {
|
||||
return nil, nil, errs
|
||||
}
|
||||
|
||||
packersdk.LogSecretFilter.Set(b.config.AlicloudAccessKey, b.config.AlicloudSecretKey)
|
||||
packer.LogSecretFilter.Set(b.config.AlicloudAccessKey, b.config.AlicloudSecretKey)
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
|
||||
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
|
||||
|
||||
client, err := b.config.Client()
|
||||
if err != nil {
|
||||
@@ -165,8 +163,8 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
||||
b.config.SSHPrivateIp),
|
||||
SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(),
|
||||
},
|
||||
&commonsteps.StepProvision{},
|
||||
&commonsteps.StepCleanupTempKeys{
|
||||
&common.StepProvision{},
|
||||
&common.StepCleanupTempKeys{
|
||||
Comm: &b.config.RunConfig.Comm,
|
||||
},
|
||||
&stepStopAlicloudInstance{
|
||||
@@ -207,7 +205,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
||||
})
|
||||
|
||||
// Run!
|
||||
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
b.runner.Run(ctx, state)
|
||||
|
||||
// If there was an error, return that
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
// Code generated by "mapstructure-to-hcl2 -type Config,AlicloudDiskDevice"; DO NOT EDIT.
|
||||
|
||||
package ecs
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"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.
|
||||
@@ -48,109 +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"`
|
||||
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
|
||||
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 []config.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"`
|
||||
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
|
||||
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
|
||||
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.
|
||||
@@ -167,11 +154,10 @@ 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_core_version": &hcldec.AttrSpec{Name: "packer_core_version", 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_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},
|
||||
@@ -193,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((*config.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},
|
||||
@@ -226,16 +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},
|
||||
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, 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},
|
||||
@@ -244,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},
|
||||
@@ -261,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},
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
builderT "github.com/hashicorp/packer/helper/builder/testing"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
const defaultTestRegion = "cn-beijing"
|
||||
@@ -104,7 +104,7 @@ const testBuilderAccWithDiskSettings = `
|
||||
}`
|
||||
|
||||
func checkImageDisksSettings() builderT.TestCheckFunc {
|
||||
return func(artifacts []packersdk.Artifact) error {
|
||||
return func(artifacts []packer.Artifact) error {
|
||||
if len(artifacts) > 1 {
|
||||
return fmt.Errorf("more than 1 artifact")
|
||||
}
|
||||
@@ -215,7 +215,7 @@ const testBuilderAccIgnoreDataDisks = `
|
||||
}`
|
||||
|
||||
func checkIgnoreDataDisks() builderT.TestCheckFunc {
|
||||
return func(artifacts []packersdk.Artifact) error {
|
||||
return func(artifacts []packer.Artifact) error {
|
||||
if len(artifacts) > 1 {
|
||||
return fmt.Errorf("more than 1 artifact")
|
||||
}
|
||||
@@ -308,7 +308,7 @@ const testBuilderAccRegionCopy = `
|
||||
`
|
||||
|
||||
func checkRegionCopy(regions []string) builderT.TestCheckFunc {
|
||||
return func(artifacts []packersdk.Artifact) error {
|
||||
return func(artifacts []packer.Artifact) error {
|
||||
if len(artifacts) > 1 {
|
||||
return fmt.Errorf("more than 1 artifact")
|
||||
}
|
||||
@@ -422,6 +422,7 @@ func TestBuilderAcc_ECSImageSharing(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// share with catsby
|
||||
const testBuilderAccSharing = `
|
||||
{
|
||||
"builders": [{
|
||||
@@ -438,7 +439,7 @@ const testBuilderAccSharing = `
|
||||
`
|
||||
|
||||
func checkECSImageSharing(uid string) builderT.TestCheckFunc {
|
||||
return func(artifacts []packersdk.Artifact) error {
|
||||
return func(artifacts []packer.Artifact) error {
|
||||
if len(artifacts) > 1 {
|
||||
return fmt.Errorf("more than 1 artifact")
|
||||
}
|
||||
@@ -534,7 +535,7 @@ const testBuilderAccForceDeleteSnapshot = `
|
||||
`
|
||||
|
||||
func checkSnapshotsDeleted(snapshotIds []string) builderT.TestCheckFunc {
|
||||
return func(artifacts []packersdk.Artifact) error {
|
||||
return func(artifacts []packer.Artifact) error {
|
||||
// Verify the snapshots are gone
|
||||
client, _ := testAliyunClient()
|
||||
data, err := json.Marshal(snapshotIds)
|
||||
@@ -587,7 +588,7 @@ const testBuilderAccImageTags = `
|
||||
}`
|
||||
|
||||
func checkImageTags() builderT.TestCheckFunc {
|
||||
return func(artifacts []packersdk.Artifact) error {
|
||||
return func(artifacts []packer.Artifact) error {
|
||||
if len(artifacts) > 1 {
|
||||
return fmt.Errorf("more than 1 artifact")
|
||||
}
|
||||
@@ -716,7 +717,7 @@ const testBuilderAccDataDiskEncrypted = `
|
||||
}`
|
||||
|
||||
func checkDataDiskEncrypted() builderT.TestCheckFunc {
|
||||
return func(artifacts []packersdk.Artifact) error {
|
||||
return func(artifacts []packer.Artifact) error {
|
||||
if len(artifacts) > 1 {
|
||||
return fmt.Errorf("more than 1 artifact")
|
||||
}
|
||||
@@ -815,7 +816,7 @@ const testBuilderAccSystemDiskEncrypted = `
|
||||
}`
|
||||
|
||||
func checkSystemDiskEncrypted() builderT.TestCheckFunc {
|
||||
return func(artifacts []packersdk.Artifact) error {
|
||||
return func(artifacts []packer.Artifact) error {
|
||||
if len(artifacts) > 1 {
|
||||
return fmt.Errorf("more than 1 artifact")
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
helperconfig "github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
helperconfig "github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func testBuilderConfig() map[string]interface{} {
|
||||
@@ -24,7 +24,7 @@ func testBuilderConfig() map[string]interface{} {
|
||||
func TestBuilder_ImplementsBuilder(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &Builder{}
|
||||
if _, ok := raw.(packersdk.Builder); !ok {
|
||||
if _, ok := raw.(packer.Builder); !ok {
|
||||
t.Fatalf("Builder should be a builder")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,19 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// The "AlicloudDiskDevice" object us used for the `ECSSystemDiskMapping` and
|
||||
// `ECSImagesDiskMappings` options, and contains the following fields:
|
||||
type AlicloudDiskDevice struct {
|
||||
// The value of disk name is blank by default. [2,
|
||||
// 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:
|
||||
// Category of the system disk. Optional values
|
||||
// are:
|
||||
// - cloud - general cloud disk
|
||||
// - cloud_efficiency - efficiency cloud disk
|
||||
// - cloud_ssd - cloud SSD
|
||||
@@ -32,12 +31,10 @@ type AlicloudDiskDevice struct {
|
||||
// Snapshots are used to create the data
|
||||
// disk After this parameter is specified, Size is ignored. The actual
|
||||
// size of the created disk is the size of the specified snapshot.
|
||||
// This field is only used in the ECSImagesDiskMappings option, not
|
||||
// the ECSSystemDiskMapping option.
|
||||
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:
|
||||
@@ -46,122 +43,160 @@ type AlicloudDiskDevice struct {
|
||||
// such as /dev/xvdb It is null unless the Status is In_use.
|
||||
Device string `mapstructure:"disk_device" required:"false"`
|
||||
// Whether or not to encrypt the data disk.
|
||||
// If this option is set to true, the data disk will be encryped and
|
||||
// corresponding snapshot in the target image will also be encrypted. By
|
||||
// If this option is set to true, the data disk will be encryped and corresponding snapshot in the target image will also be encrypted. By
|
||||
// default, if this is an extra data disk, Packer will not encrypt the
|
||||
// data disk. Otherwise, Packer will keep the encryption setting to what
|
||||
// it was in the source image. Please refer to Introduction of ECS disk
|
||||
// encryption for more details.
|
||||
// it was in the source image. Please refer to Introduction of ECS disk encryption
|
||||
// for more details.
|
||||
Encrypted config.Trilean `mapstructure:"disk_encrypted" required:"false"`
|
||||
}
|
||||
|
||||
// The "AlicloudDiskDevices" object is used to define disk mappings for your
|
||||
// instance.
|
||||
type AlicloudDiskDevices struct {
|
||||
// Image disk mapping for the system disk.
|
||||
// See the [disk device configuration](#disk-devices-configuration) section
|
||||
// for more information on options.
|
||||
// Usage example:
|
||||
// Image disk mapping for system
|
||||
// disk.
|
||||
// - `disk_category` (string) - Category of the system disk. Optional values
|
||||
// are:
|
||||
// - `cloud` - general cloud disk
|
||||
// - `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.
|
||||
//
|
||||
// - `disk_description` (string) - 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://`.
|
||||
//
|
||||
// - `disk_name` (string) - The value of disk name is blank by default. \[2,
|
||||
// 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://`.
|
||||
//
|
||||
// - `disk_size` (number) - Size of the system disk, measured in GiB. Value
|
||||
// range: \[20, 500\]. The specified value must be equal to or greater
|
||||
// than max{20, ImageSize}. Default value: max{40, ImageSize}.
|
||||
//
|
||||
// ```json
|
||||
// "builders": [{
|
||||
// "type":"alicloud-ecs",
|
||||
// "system_disk_mapping": {
|
||||
// "disk_size": 50,
|
||||
// "disk_name": "mydisk"
|
||||
// },
|
||||
// ...
|
||||
// }
|
||||
// ```
|
||||
ECSSystemDiskMapping AlicloudDiskDevice `mapstructure:"system_disk_mapping" required:"false"`
|
||||
// Add one or more data disks to the image.
|
||||
// See the [disk device configuration](#disk-devices-configuration) section
|
||||
// for more information on options.
|
||||
// Usage example:
|
||||
// Add one or more data
|
||||
// disks to the image.
|
||||
//
|
||||
// - `disk_category` (string) - Category of the data disk. Optional values
|
||||
// are:
|
||||
// - `cloud` - general cloud disk
|
||||
// - `cloud_efficiency` - efficiency cloud disk
|
||||
// - `cloud_ssd` - cloud SSD
|
||||
//
|
||||
// Default value: cloud.
|
||||
//
|
||||
// - `disk_delete_with_instance` (boolean) - Whether or not the disk is
|
||||
// released along with the instance:
|
||||
// - True indicates that when the instance is released, this disk will
|
||||
// be released with it
|
||||
// - False indicates that when the instance is released, this disk will
|
||||
// be retained.
|
||||
// - `disk_description` (string) - 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://`.
|
||||
//
|
||||
// - `disk_device` (string) - Device information of the related instance:
|
||||
// such as `/dev/xvdb` It is null unless the Status is In\_use.
|
||||
//
|
||||
// - `disk_name` (string) - The value of disk name is blank by default. \[2,
|
||||
// 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://`.
|
||||
//
|
||||
// - `disk_size` (number) - Size of the data disk, in GB, values range:
|
||||
// - `cloud` - 5 \~ 2000
|
||||
// - `cloud_efficiency` - 20 \~ 2048
|
||||
// - `cloud_ssd` - 20 \~ 2048
|
||||
//
|
||||
// The value should be equal to or greater than the size of the specific
|
||||
// SnapshotId.
|
||||
//
|
||||
// - `disk_snapshot_id` (string) - Snapshots are used to create the data
|
||||
// disk After this parameter is specified, Size is ignored. The actual
|
||||
// size of the created disk is the size of the specified snapshot.
|
||||
//
|
||||
// Snapshots from on or before July 15, 2013 cannot be used to create a
|
||||
// disk.
|
||||
//
|
||||
// - `disk_encrypted` (boolean) - Whether or not to encrypt the data disk.
|
||||
// If this option is set to true, the data disk will be encryped and corresponding snapshot in the target image will also be encrypted. By
|
||||
// default, if this is an extra data disk, Packer will not encrypt the
|
||||
// data disk. Otherwise, Packer will keep the encryption setting to what
|
||||
// it was in the source image. Please refer to Introduction of [ECS disk encryption](https://www.alibabacloud.com/help/doc-detail/59643.htm)
|
||||
// for more details.
|
||||
//
|
||||
// ```json
|
||||
// "builders": [{
|
||||
// "type":"alicloud-ecs",
|
||||
// "image_disk_mappings": [
|
||||
// {
|
||||
// "disk_snapshot_id": "someid",
|
||||
// "disk_device": "dev/xvdb"
|
||||
// }
|
||||
// ],
|
||||
// ...
|
||||
// }
|
||||
// ```
|
||||
ECSImagesDiskMappings []AlicloudDiskDevice `mapstructure:"image_disk_mappings" required:"false"`
|
||||
}
|
||||
|
||||
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/templates/hcl_templates/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
AlicloudImageTag config.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 {
|
||||
@@ -193,5 +228,9 @@ func (c *AlicloudImageConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
c.AlicloudImageDestinationRegions = regions
|
||||
}
|
||||
|
||||
return errs
|
||||
if len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func cleanUpMessage(state multistep.StateBag, module string) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if cancelled || halted {
|
||||
ui.Say(fmt.Sprintf("Deleting %s because of cancellation or error...", module))
|
||||
@@ -22,7 +22,7 @@ func cleanUpMessage(state multistep.StateBag, module string) {
|
||||
}
|
||||
|
||||
func halt(state multistep.StateBag, err error, prefix string) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if prefix != "" {
|
||||
err = fmt.Errorf("%s: %s", prefix, err)
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
type RunConfig struct {
|
||||
@@ -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.
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
)
|
||||
|
||||
func testConfig() *RunConfig {
|
||||
|
||||
@@ -3,7 +3,7 @@ package ecs
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepAttachKeyPair struct {
|
||||
@@ -21,7 +21,7 @@ var attachKeyPairNotRetryErrors = []string{
|
||||
}
|
||||
|
||||
func (s *stepAttachKeyPair) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
config := state.Get("config").(*Config)
|
||||
instance := state.Get("instance").(*ecs.Instance)
|
||||
@@ -52,7 +52,7 @@ func (s *stepAttachKeyPair) Run(ctx context.Context, state multistep.StateBag) m
|
||||
func (s *stepAttachKeyPair) Cleanup(state multistep.StateBag) {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
config := state.Get("config").(*Config)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
instance := state.Get("instance").(*ecs.Instance)
|
||||
keyPairName := config.Comm.SSHKeyPairName
|
||||
if keyPairName == "" {
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepCheckAlicloudSourceImage struct {
|
||||
@@ -16,7 +16,7 @@ type stepCheckAlicloudSourceImage struct {
|
||||
func (s *stepCheckAlicloudSourceImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
config := state.Get("config").(*Config)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
describeImagesRequest := ecs.CreateDescribeImagesRequest()
|
||||
describeImagesRequest.RegionId = config.AlicloudRegion
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepConfigAlicloudEIP struct {
|
||||
@@ -28,7 +28,7 @@ var allocateEipAddressRetryErrors = []string{
|
||||
|
||||
func (s *stepConfigAlicloudEIP) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
instance := state.Get("instance").(*ecs.Instance)
|
||||
|
||||
if s.SSHPrivateIp {
|
||||
@@ -96,7 +96,7 @@ func (s *stepConfigAlicloudEIP) Cleanup(state multistep.StateBag) {
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
instance := state.Get("instance").(*ecs.Instance)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
unassociateEipAddressRequest := ecs.CreateUnassociateEipAddressRequest()
|
||||
unassociateEipAddressRequest.AllocationId = s.allocatedId
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"runtime"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepConfigAlicloudKeyPair struct {
|
||||
@@ -22,7 +22,7 @@ type stepConfigAlicloudKeyPair struct {
|
||||
}
|
||||
|
||||
func (s *stepConfigAlicloudKeyPair) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if s.Comm.SSHPrivateKeyFile != "" {
|
||||
ui.Say("Using existing SSH private key")
|
||||
@@ -108,7 +108,7 @@ func (s *stepConfigAlicloudKeyPair) Cleanup(state multistep.StateBag) {
|
||||
}
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
// Remove the keypair
|
||||
ui.Say("Deleting temporary keypair...")
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepConfigAlicloudPublicIP struct {
|
||||
@@ -17,7 +17,7 @@ type stepConfigAlicloudPublicIP struct {
|
||||
|
||||
func (s *stepConfigAlicloudPublicIP) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
instance := state.Get("instance").(*ecs.Instance)
|
||||
|
||||
if s.SSHPrivateIp {
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepConfigAlicloudSecurityGroup struct {
|
||||
@@ -30,7 +30,7 @@ var deleteSecurityGroupRetryErrors = []string{
|
||||
|
||||
func (s *stepConfigAlicloudSecurityGroup) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
networkType := state.Get("networktype").(InstanceNetWork)
|
||||
|
||||
if len(s.SecurityGroupId) != 0 {
|
||||
@@ -117,7 +117,7 @@ func (s *stepConfigAlicloudSecurityGroup) Cleanup(state multistep.StateBag) {
|
||||
cleanUpMessage(state, "security group")
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
_, err := client.WaitForExpected(&WaitForExpectArgs{
|
||||
RequestFunc: func() (responses.AcsResponse, error) {
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepConfigAlicloudVPC struct {
|
||||
@@ -35,7 +35,7 @@ var deleteVpcRetryErrors = []string{
|
||||
func (s *stepConfigAlicloudVPC) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if len(s.VpcId) != 0 {
|
||||
describeVpcsRequest := ecs.CreateDescribeVpcsRequest()
|
||||
@@ -118,7 +118,7 @@ func (s *stepConfigAlicloudVPC) Cleanup(state multistep.StateBag) {
|
||||
cleanUpMessage(state, "VPC")
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
_, err := client.WaitForExpected(&WaitForExpectArgs{
|
||||
RequestFunc: func() (responses.AcsResponse, error) {
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepConfigAlicloudVSwitch struct {
|
||||
@@ -33,7 +33,7 @@ var deleteVSwitchRetryErrors = []string{
|
||||
|
||||
func (s *stepConfigAlicloudVSwitch) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vpcId := state.Get("vpcid").(string)
|
||||
config := state.Get("config").(*Config)
|
||||
|
||||
@@ -176,7 +176,7 @@ func (s *stepConfigAlicloudVSwitch) Cleanup(state multistep.StateBag) {
|
||||
cleanUpMessage(state, "vSwitch")
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
_, err := client.WaitForExpected(&WaitForExpectArgs{
|
||||
RequestFunc: func() (responses.AcsResponse, error) {
|
||||
|
||||
@@ -5,13 +5,13 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/random"
|
||||
"github.com/hashicorp/packer/common/random"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepCreateAlicloudImage struct {
|
||||
@@ -27,7 +27,7 @@ var createImageRetryErrors = []string{
|
||||
func (s *stepCreateAlicloudImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
tempImageName := config.AlicloudImageName
|
||||
if config.ImageEncrypted.True() {
|
||||
@@ -95,7 +95,7 @@ func (s *stepCreateAlicloudImage) Cleanup(state multistep.StateBag) {
|
||||
}
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if !cancelled && !halted && encryptedSet {
|
||||
ui.Say(fmt.Sprintf("Deleting temporary image %s(%s) and related snapshots after finishing encryption...", s.image.ImageId, s.image.ImageName))
|
||||
|
||||
@@ -7,14 +7,14 @@ import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
confighelper "github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
confighelper "github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepCreateAlicloudInstance struct {
|
||||
@@ -41,7 +41,7 @@ var deleteInstanceRetryErrors = []string{
|
||||
|
||||
func (s *stepCreateAlicloudInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Creating instance...")
|
||||
createInstanceRequest, err := s.buildCreateInstanceRequest(state)
|
||||
@@ -91,7 +91,7 @@ func (s *stepCreateAlicloudInstance) Cleanup(state multistep.StateBag) {
|
||||
cleanUpMessage(state, "instance")
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
_, err := client.WaitForExpected(&WaitForExpectArgs{
|
||||
RequestFunc: func() (responses.AcsResponse, error) {
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepCreateAlicloudSnapshot struct {
|
||||
@@ -19,7 +19,7 @@ type stepCreateAlicloudSnapshot struct {
|
||||
func (s *stepCreateAlicloudSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
instance := state.Get("instance").(*ecs.Instance)
|
||||
|
||||
describeDisksRequest := ecs.CreateDescribeDisksRequest()
|
||||
@@ -77,7 +77,7 @@ func (s *stepCreateAlicloudSnapshot) Cleanup(state multistep.StateBag) {
|
||||
}
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Deleting the snapshot because of cancellation or error...")
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepCreateTags struct {
|
||||
@@ -16,7 +16,7 @@ type stepCreateTags struct {
|
||||
func (s *stepCreateTags) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
imageId := state.Get("alicloudimage").(string)
|
||||
snapshotIds := state.Get("alicloudsnapshots").([]string)
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepDeleteAlicloudImageSnapshots struct {
|
||||
@@ -54,7 +54,7 @@ func (s *stepDeleteAlicloudImageSnapshots) Run(ctx context.Context, state multis
|
||||
|
||||
func (s *stepDeleteAlicloudImageSnapshots) deleteImageAndSnapshots(state multistep.StateBag, imageName string, region string) error {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
describeImagesRequest := ecs.CreateDescribeImagesRequest()
|
||||
describeImagesRequest.RegionId = region
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepPreValidate struct {
|
||||
@@ -27,7 +27,7 @@ func (s *stepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul
|
||||
}
|
||||
|
||||
func (s *stepPreValidate) validateRegions(state multistep.StateBag) error {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
config := state.Get("config").(*Config)
|
||||
|
||||
if config.AlicloudSkipValidation {
|
||||
@@ -37,13 +37,13 @@ func (s *stepPreValidate) validateRegions(state multistep.StateBag) error {
|
||||
|
||||
ui.Say("Prevalidating source region and copied regions...")
|
||||
|
||||
var errs *packersdk.MultiError
|
||||
var errs *packer.MultiError
|
||||
if err := config.ValidateRegion(config.AlicloudRegion); err != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, err)
|
||||
errs = packer.MultiErrorAppend(errs, err)
|
||||
}
|
||||
for _, region := range config.AlicloudImageDestinationRegions {
|
||||
if err := config.ValidateRegion(region); err != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, err)
|
||||
errs = packer.MultiErrorAppend(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (s *stepPreValidate) validateRegions(state multistep.StateBag) error {
|
||||
}
|
||||
|
||||
func (s *stepPreValidate) validateDestImageName(state multistep.StateBag) error {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
config := state.Get("config").(*Config)
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
confighelper "github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
confighelper "github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepRegionCopyAlicloudImage struct {
|
||||
@@ -31,7 +31,7 @@ func (s *stepRegionCopyAlicloudImage) Run(ctx context.Context, state multistep.S
|
||||
}
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
srcImageId := state.Get("alicloudimage").(string)
|
||||
alicloudImages := state.Get("alicloudimages").(map[string]string)
|
||||
@@ -83,7 +83,7 @@ func (s *stepRegionCopyAlicloudImage) Cleanup(state multistep.StateBag) {
|
||||
return
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Say(fmt.Sprintf("Stopping copy image because cancellation or error..."))
|
||||
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepRunAlicloudInstance struct {
|
||||
@@ -15,7 +15,7 @@ type stepRunAlicloudInstance struct {
|
||||
|
||||
func (s *stepRunAlicloudInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
instance := state.Get("instance").(*ecs.Instance)
|
||||
|
||||
startInstanceRequest := ecs.CreateStartInstanceRequest()
|
||||
@@ -42,7 +42,7 @@ func (s *stepRunAlicloudInstance) Cleanup(state multistep.StateBag) {
|
||||
return
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
instance := state.Get("instance").(*ecs.Instance)
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepShareAlicloudImage struct {
|
||||
@@ -41,7 +41,7 @@ func (s *stepShareAlicloudImage) Cleanup(state multistep.StateBag) {
|
||||
return
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
alicloudImages := state.Get("alicloudimages").(map[string]string)
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type stepStopAlicloudInstance struct {
|
||||
@@ -20,7 +20,7 @@ type stepStopAlicloudInstance struct {
|
||||
func (s *stepStopAlicloudInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*ClientWrapper)
|
||||
instance := state.Get("instance").(*ecs.Instance)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if !s.DisableStop {
|
||||
ui.Say(fmt.Sprintf("Stopping instance: %s", instance.InstanceId))
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer-plugin-sdk/version"
|
||||
packerVersion "github.com/hashicorp/packer/version"
|
||||
)
|
||||
|
||||
var AlicloudPluginVersion *version.PluginVersion
|
||||
|
||||
func init() {
|
||||
AlicloudPluginVersion = version.InitializePluginVersion(
|
||||
packerVersion.Version, packerVersion.VersionPrerelease)
|
||||
}
|
||||
@@ -10,20 +10,18 @@ package chroot
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-sdk/chroot"
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/packerbuilderdata"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer/builder"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/chroot"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// The unique ID for this builder
|
||||
@@ -49,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
|
||||
@@ -91,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"`
|
||||
@@ -122,74 +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/legacy_json_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/templates/hcl_templates/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
RootVolumeTag config.KeyValues `mapstructure:"root_volume_tag" required:"false"`
|
||||
// Whether or not to encrypt the volumes that are *launched*. By default, Packer will keep
|
||||
// the encryption setting to what it was in the source image when set to `false`. Setting true will
|
||||
// always result in an encrypted one.
|
||||
RootVolumeEncryptBoot config.Trilean `mapstructure:"root_volume_encrypt_boot" required:"false"`
|
||||
// ID, alias or ARN of the KMS key to use for *launched* volumes encryption.
|
||||
//
|
||||
// Set this value if you select `root_volume_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 set this
|
||||
// and `root_volume_encrypt_boot` to `true` and not use `encrypt_boot` and `kms_key_id`. 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 -
|
||||
// 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/`.
|
||||
RootVolumeKmsKeyId string `mapstructure:"root_volume_kms_key_id" 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"`
|
||||
@@ -215,18 +189,14 @@ func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstruct
|
||||
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
b.config.ctx.Funcs = awscommon.TemplateFuncs
|
||||
err := config.Decode(&b.config, &config.DecodeOpts{
|
||||
PluginType: BuilderId,
|
||||
Interpolate: true,
|
||||
InterpolateContext: &b.config.ctx,
|
||||
InterpolateFilter: &interpolate.RenderFilter{
|
||||
Exclude: []string{
|
||||
"ami_description",
|
||||
"snapshot_tags",
|
||||
"snapshot_tag",
|
||||
"tags",
|
||||
"tag",
|
||||
"root_volume_tags",
|
||||
"root_volume_tag",
|
||||
"command_wrapper",
|
||||
"post_mount_commands",
|
||||
"pre_mount_commands",
|
||||
@@ -281,17 +251,16 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
}
|
||||
|
||||
// Accumulate any errors or warnings
|
||||
var errs *packersdk.MultiError
|
||||
var errs *packer.MultiError
|
||||
var warns []string
|
||||
|
||||
errs = packersdk.MultiErrorAppend(errs, b.config.RootVolumeTag.CopyOn(&b.config.RootVolumeTags)...)
|
||||
errs = packersdk.MultiErrorAppend(errs, b.config.AccessConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs,
|
||||
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)...)
|
||||
|
||||
for _, mounts := range b.config.ChrootMounts {
|
||||
if len(mounts) != 3 {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("Each chroot_mounts entry should be three elements."))
|
||||
break
|
||||
}
|
||||
@@ -302,56 +271,45 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
warns = append(warns, "source_ami and source_ami_filter are unused when from_scratch is true")
|
||||
}
|
||||
if b.config.RootVolumeSize == 0 {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("root_volume_size is required with from_scratch."))
|
||||
}
|
||||
if len(b.config.PreMountCommands) == 0 {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("pre_mount_commands is required with from_scratch."))
|
||||
}
|
||||
if b.config.AMIVirtType == "" {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("ami_virtualization_type is required with from_scratch."))
|
||||
}
|
||||
if b.config.RootDeviceName == "" {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("root_device_name is required with from_scratch."))
|
||||
}
|
||||
if len(b.config.AMIMappings) == 0 {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("ami_block_device_mappings is required with from_scratch."))
|
||||
}
|
||||
} else {
|
||||
if b.config.SourceAmi == "" && b.config.SourceAmiFilter.Empty() {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("source_ami or source_ami_filter is required."))
|
||||
}
|
||||
if len(b.config.AMIMappings) > 0 && b.config.RootDeviceName != "" {
|
||||
if b.config.RootVolumeSize == 0 {
|
||||
// Although, they can specify the device size in the block
|
||||
// device mapping, it's easier to be specific here.
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("root_volume_size is required if ami_block_device_mappings is specified"))
|
||||
}
|
||||
warns = append(warns, "ami_block_device_mappings from source image will be completely overwritten")
|
||||
} else if len(b.config.AMIMappings) > 0 {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("If ami_block_device_mappings is specified, root_device_name must be specified"))
|
||||
} else if b.config.RootDeviceName != "" {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("If root_device_name is specified, ami_block_device_mappings must be specified"))
|
||||
}
|
||||
|
||||
if b.config.RootVolumeKmsKeyId != "" {
|
||||
if b.config.RootVolumeEncryptBoot.False() {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs, errors.New("If you have set root_volume_kms_key_id, root_volume_encrypt_boot must also be true."))
|
||||
} else if b.config.RootVolumeEncryptBoot.True() && !awscommon.ValidateKmsKey(b.config.RootVolumeKmsKeyId) {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs, fmt.Errorf("%q is not a valid KMS Key Id.", b.config.RootVolumeKmsKeyId))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
valid := false
|
||||
for _, validArch := range []string{"x86_64", "arm64"} {
|
||||
@@ -361,21 +319,19 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
}
|
||||
}
|
||||
if !valid {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New(`The only valid ami_architecture values are "x86_64" and "arm64"`))
|
||||
errs = packer.MultiErrorAppend(errs, errors.New(`The only valid ami_architecture values are "x86_64" and "arm64"`))
|
||||
}
|
||||
|
||||
if errs != nil && len(errs.Errors) > 0 {
|
||||
return nil, warns, errs
|
||||
}
|
||||
|
||||
packersdk.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
|
||||
generatedData := awscommon.GetGeneratedDataList()
|
||||
generatedData = append(generatedData, "Device", "MountPath")
|
||||
|
||||
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
|
||||
generatedData := []string{"SourceAMIName", "Device", "MountPath"}
|
||||
return generatedData, warns, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
|
||||
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
|
||||
if runtime.GOOS != "linux" {
|
||||
return nil, errors.New("The amazon-chroot builder only works on Linux environments.")
|
||||
}
|
||||
@@ -402,7 +358,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
state.Put("wrappedCommand", common.CommandWrapper(wrappedCommand))
|
||||
generatedData := &packerbuilderdata.GeneratedData{State: state}
|
||||
generatedData := &builder.GeneratedData{State: state}
|
||||
|
||||
// Build the steps
|
||||
steps := []multistep.Step{
|
||||
@@ -432,17 +388,12 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
||||
GeneratedData: generatedData,
|
||||
},
|
||||
&StepCreateVolume{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
RootVolumeType: b.config.RootVolumeType,
|
||||
RootVolumeSize: b.config.RootVolumeSize,
|
||||
RootVolumeTags: b.config.RootVolumeTags,
|
||||
RootVolumeEncryptBoot: b.config.RootVolumeEncryptBoot,
|
||||
RootVolumeKmsKeyId: b.config.RootVolumeKmsKeyId,
|
||||
Ctx: b.config.ctx,
|
||||
},
|
||||
&StepAttachVolume{
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
RootVolumeType: b.config.RootVolumeType,
|
||||
RootVolumeSize: b.config.RootVolumeSize,
|
||||
RootVolumeTags: b.config.RootVolumeTags,
|
||||
Ctx: b.config.ctx,
|
||||
},
|
||||
&StepAttachVolume{},
|
||||
&StepEarlyUnflock{},
|
||||
&chroot.StepPreMountCommands{
|
||||
Commands: b.config.PreMountCommands,
|
||||
@@ -461,14 +412,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
||||
&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,
|
||||
@@ -481,7 +427,6 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
||||
EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
|
||||
EnableAMIENASupport: b.config.AMIENASupport,
|
||||
AMISkipBuildRegion: b.config.AMISkipBuildRegion,
|
||||
PollingConfig: b.config.PollingConfig,
|
||||
},
|
||||
&awscommon.StepAMIRegionCopy{
|
||||
AccessConfig: &b.config.AccessConfig,
|
||||
@@ -510,7 +455,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
||||
)
|
||||
|
||||
// Run!
|
||||
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
b.runner.Run(ctx, state)
|
||||
|
||||
// If there was an error, return that
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
// Code generated by "mapstructure-to-hcl2 -type Config,BlockDevices,BlockDevice"; DO NOT EDIT.
|
||||
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
@@ -12,74 +10,64 @@ import (
|
||||
// FlatConfig is an auto-generated flat version of Config.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatConfig struct {
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
|
||||
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 []config.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 []config.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"`
|
||||
AssumeRole *common.FlatAssumeRoleConfig `mapstructure:"assume_role" required:"false" cty:"assume_role" hcl:"assume_role"`
|
||||
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2" hcl:"custom_endpoint_ec2"`
|
||||
CredsFilename *string `mapstructure:"shared_credentials_file" required:"false" cty:"shared_credentials_file" hcl:"shared_credentials_file"`
|
||||
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"`
|
||||
SkipCredsValidation *bool `mapstructure:"skip_credential_validation" cty:"skip_credential_validation" hcl:"skip_credential_validation"`
|
||||
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 []config.FlatKeyValue `mapstructure:"root_volume_tag" required:"false" cty:"root_volume_tag" hcl:"root_volume_tag"`
|
||||
RootVolumeEncryptBoot *bool `mapstructure:"root_volume_encrypt_boot" required:"false" cty:"root_volume_encrypt_boot" hcl:"root_volume_encrypt_boot"`
|
||||
RootVolumeKmsKeyId *string `mapstructure:"root_volume_kms_key_id" required:"false" cty:"root_volume_kms_key_id" hcl:"root_volume_kms_key_id"`
|
||||
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.
|
||||
@@ -96,11 +84,10 @@ 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_core_version": &hcldec.AttrSpec{Name: "packer_core_version", 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_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},
|
||||
@@ -110,24 +97,20 @@ 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((*config.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((*config.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},
|
||||
"assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*common.FlatAssumeRoleConfig)(nil).HCL2Spec())},
|
||||
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
|
||||
"shared_credentials_file": &hcldec.AttrSpec{Name: "shared_credentials_file", Type: cty.String, Required: false},
|
||||
"decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false},
|
||||
"insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false},
|
||||
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
|
||||
@@ -136,10 +119,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
|
||||
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
|
||||
"skip_metadata_api_check": &hcldec.AttrSpec{Name: "skip_metadata_api_check", Type: cty.Bool, Required: false},
|
||||
"skip_credential_validation": &hcldec.AttrSpec{Name: "skip_credential_validation", 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},
|
||||
@@ -157,10 +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((*config.FlatKeyValue)(nil).HCL2Spec())},
|
||||
"root_volume_encrypt_boot": &hcldec.AttrSpec{Name: "root_volume_encrypt_boot", Type: cty.Bool, Required: false},
|
||||
"root_volume_kms_key_id": &hcldec.AttrSpec{Name: "root_volume_kms_key_id", Type: cty.String, Required: false},
|
||||
"root_volume_tags": &hcldec.BlockAttrsSpec{TypeName: "root_volume_tags", ElementType: cty.String, Required: false},
|
||||
"ami_architecture": &hcldec.AttrSpec{Name: "ami_architecture", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
|
||||
@@ -3,7 +3,7 @@ package chroot
|
||||
import (
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
@@ -19,7 +19,7 @@ func testConfig() map[string]interface{} {
|
||||
func TestBuilder_ImplementsBuilder(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &Builder{}
|
||||
if _, ok := raw.(packersdk.Builder); !ok {
|
||||
if _, ok := raw.(packer.Builder); !ok {
|
||||
t.Fatalf("Builder should be a builder")
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
)
|
||||
|
||||
func TestCopyFile(t *testing.T) {
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepAttachVolume attaches the previously created volume to an
|
||||
@@ -19,16 +19,15 @@ 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 {
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
device := state.Get("device").(string)
|
||||
instance := state.Get("instance").(*ec2.Instance)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
volumeId := state.Get("volume_id").(string)
|
||||
|
||||
// For the API call, it expects "sd" prefixed devices.
|
||||
@@ -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)
|
||||
@@ -65,7 +64,7 @@ func (s *StepAttachVolume) Run(ctx context.Context, state multistep.StateBag) mu
|
||||
}
|
||||
|
||||
func (s *StepAttachVolume) Cleanup(state multistep.StateBag) {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
if err := s.CleanupFunc(state); err != nil {
|
||||
ui.Error(err.Error())
|
||||
}
|
||||
@@ -77,7 +76,7 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
|
||||
}
|
||||
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Detaching EBS volume...")
|
||||
_, err := ec2conn.DetachVolume(&ec2.DetachVolumeInput{VolumeId: &s.volumeId})
|
||||
@@ -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,7 +3,7 @@ package chroot
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/chroot"
|
||||
"github.com/hashicorp/packer/common/chroot"
|
||||
)
|
||||
|
||||
func TestAttachVolumeCleanupFunc_ImplementsCleanupFunc(t *testing.T) {
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepCheckRootDevice makes sure the root device on the AMI is EBS-backed.
|
||||
@@ -14,7 +14,7 @@ type StepCheckRootDevice struct{}
|
||||
|
||||
func (s *StepCheckRootDevice) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
image := state.Get("source_image").(*ec2.Image)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Checking the root device on source AMI...")
|
||||
|
||||
|
||||
@@ -8,11 +8,10 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
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"
|
||||
)
|
||||
|
||||
// StepCreateVolume creates a new volume from the snapshot of the root
|
||||
@@ -21,23 +20,20 @@ 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
|
||||
RootVolumeEncryptBoot config.Trilean
|
||||
RootVolumeKmsKeyId string
|
||||
Ctx interpolate.Context
|
||||
volumeId string
|
||||
RootVolumeSize int64
|
||||
RootVolumeType string
|
||||
RootVolumeTags awscommon.TagMap
|
||||
Ctx interpolate.Context
|
||||
}
|
||||
|
||||
func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
instance := state.Get("instance").(*ec2.Instance)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
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)
|
||||
@@ -114,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)
|
||||
@@ -132,7 +128,7 @@ func (s *StepCreateVolume) Cleanup(state multistep.StateBag) {
|
||||
}
|
||||
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Deleting the created EBS volume...")
|
||||
_, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeId: &s.volumeId})
|
||||
@@ -151,21 +147,11 @@ func (s *StepCreateVolume) buildCreateVolumeInput(az string, rootDevice *ec2.Blo
|
||||
SnapshotId: rootDevice.Ebs.SnapshotId,
|
||||
VolumeType: rootDevice.Ebs.VolumeType,
|
||||
Iops: rootDevice.Ebs.Iops,
|
||||
Encrypted: rootDevice.Ebs.Encrypted,
|
||||
KmsKeyId: rootDevice.Ebs.KmsKeyId,
|
||||
}
|
||||
if s.RootVolumeSize > *rootDevice.Ebs.VolumeSize {
|
||||
createVolumeInput.Size = aws.Int64(s.RootVolumeSize)
|
||||
}
|
||||
|
||||
if s.RootVolumeEncryptBoot.True() {
|
||||
createVolumeInput.Encrypted = aws.Bool(true)
|
||||
}
|
||||
|
||||
if s.RootVolumeKmsKeyId != "" {
|
||||
createVolumeInput.KmsKeyId = aws.String(s.RootVolumeKmsKeyId)
|
||||
}
|
||||
|
||||
if s.RootVolumeType == "" || s.RootVolumeType == *rootDevice.Ebs.VolumeType {
|
||||
return createVolumeInput, nil
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
confighelper "github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -15,7 +14,6 @@ func buildTestRootDevice() *ec2.BlockDeviceMapping {
|
||||
VolumeSize: aws.Int64(10),
|
||||
SnapshotId: aws.String("snap-1234"),
|
||||
VolumeType: aws.String("gp2"),
|
||||
Encrypted: aws.Bool(false),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -74,24 +72,3 @@ func TestCreateVolume_gp2_to_io1(t *testing.T) {
|
||||
_, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCreateVolume_Encrypted(t *testing.T) {
|
||||
stepCreateVolume := StepCreateVolume{RootVolumeEncryptBoot: confighelper.TrileanFromBool(true)}
|
||||
testRootDevice := buildTestRootDevice()
|
||||
ret, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice)
|
||||
assert.NoError(t, err)
|
||||
// Ensure that the new value is equal to the the value passed in
|
||||
assert.Equal(t, confighelper.TrileanFromBool(*ret.Encrypted), stepCreateVolume.RootVolumeEncryptBoot)
|
||||
}
|
||||
|
||||
func TestCreateVolume_Custom_KMS_Key_Encrypted(t *testing.T) {
|
||||
stepCreateVolume := StepCreateVolume{
|
||||
RootVolumeEncryptBoot: confighelper.TrileanFromBool(true),
|
||||
RootVolumeKmsKeyId: "alias/1234",
|
||||
}
|
||||
testRootDevice := buildTestRootDevice()
|
||||
ret, err := stepCreateVolume.buildCreateVolumeInput("test-az", testRootDevice)
|
||||
assert.NoError(t, err)
|
||||
// Ensure that the new value is equal to the value passed in
|
||||
assert.Equal(t, *ret.KmsKeyId, stepCreateVolume.RootVolumeKmsKeyId)
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/chroot"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/common/chroot"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepEarlyUnflock unlocks the flock.
|
||||
@@ -15,7 +15,7 @@ type StepEarlyUnflock struct{}
|
||||
|
||||
func (s *StepEarlyUnflock) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
cleanup := state.Get("flock_cleanup").(chroot.Cleanup)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
log.Println("Unlocking file lock...")
|
||||
if err := cleanup.CleanupFunc(state); err != nil {
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepFlock provisions the instance within a chroot.
|
||||
@@ -20,7 +20,7 @@ type StepFlock struct {
|
||||
}
|
||||
|
||||
func (s *StepFlock) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
lockfile := "/var/lock/packer-chroot/lock"
|
||||
if err := os.MkdirAll(filepath.Dir(lockfile), 0755); err != nil {
|
||||
|
||||
@@ -3,7 +3,7 @@ package chroot
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/chroot"
|
||||
"github.com/hashicorp/packer/common/chroot"
|
||||
)
|
||||
|
||||
func TestFlockCleanupFunc_ImplementsCleanupFunc(t *testing.T) {
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepInstanceInfo verifies that this builder is running on an EC2 instance.
|
||||
@@ -18,7 +18,7 @@ type StepInstanceInfo struct{}
|
||||
func (s *StepInstanceInfo) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
session := state.Get("awsSession").(*session.Session)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
// Get our own instance ID
|
||||
ui.Say("Gathering information about this EC2 instance...")
|
||||
|
||||
@@ -10,11 +10,11 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/packerbuilderdata"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer/builder"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
type mountPathData struct {
|
||||
@@ -31,12 +31,12 @@ type StepMountDevice struct {
|
||||
MountPartition string
|
||||
|
||||
mountPath string
|
||||
GeneratedData *packerbuilderdata.GeneratedData
|
||||
GeneratedData *builder.GeneratedData
|
||||
}
|
||||
|
||||
func (s *StepMountDevice) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
device := state.Get("device").(string)
|
||||
if config.NVMEDevicePath != "" {
|
||||
// customizable device path for mounting NVME block devices on c5 and m5 HVM
|
||||
@@ -127,7 +127,7 @@ func (s *StepMountDevice) Run(ctx context.Context, state multistep.StateBag) mul
|
||||
}
|
||||
|
||||
func (s *StepMountDevice) Cleanup(state multistep.StateBag) {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
if err := s.CleanupFunc(state); err != nil {
|
||||
ui.Error(err.Error())
|
||||
}
|
||||
@@ -138,7 +138,7 @@ func (s *StepMountDevice) CleanupFunc(state multistep.StateBag) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
wrappedCommand := state.Get("wrappedCommand").(common.CommandWrapper)
|
||||
|
||||
ui.Say("Unmounting the root device...")
|
||||
|
||||
@@ -3,7 +3,7 @@ package chroot
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/chroot"
|
||||
"github.com/hashicorp/packer/common/chroot"
|
||||
)
|
||||
|
||||
func TestMountDeviceCleanupFunc_ImplementsCleanupFunc(t *testing.T) {
|
||||
|
||||
@@ -6,19 +6,19 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/packerbuilderdata"
|
||||
"github.com/hashicorp/packer/builder"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepPrepareDevice finds an available device and sets it.
|
||||
type StepPrepareDevice struct {
|
||||
GeneratedData *packerbuilderdata.GeneratedData
|
||||
GeneratedData *builder.GeneratedData
|
||||
}
|
||||
|
||||
func (s *StepPrepareDevice) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
device := config.DevicePath
|
||||
if device == "" {
|
||||
|
||||
@@ -6,16 +6,15 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/random"
|
||||
confighelper "github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common/random"
|
||||
confighelper "github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepRegisterAMI creates the AMI.
|
||||
type StepRegisterAMI struct {
|
||||
PollingConfig *awscommon.AWSPollingConfig
|
||||
RootVolumeSize int64
|
||||
EnableAMIENASupport confighelper.Trilean
|
||||
EnableAMISriovNetSupport bool
|
||||
@@ -26,7 +25,7 @@ func (s *StepRegisterAMI) Run(ctx context.Context, state multistep.StateBag) mul
|
||||
config := state.Get("config").(*Config)
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
snapshotID := state.Get("snapshot_id").(string)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Registering the AMI...")
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -3,8 +3,8 @@ package chroot
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
amazon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepSnapshot creates a snapshot of the created volume.
|
||||
@@ -16,13 +16,12 @@ 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 {
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
volumeId := state.Get("volume_id").(string)
|
||||
|
||||
ui.Say("Creating snapshot...")
|
||||
@@ -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)
|
||||
@@ -72,7 +71,7 @@ func (s *StepSnapshot) Cleanup(state multistep.StateBag) {
|
||||
|
||||
if cancelled || halted {
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Say("Removing snapshot since we cancelled or halted...")
|
||||
_, err := ec2conn.DeleteSnapshot(&ec2.DeleteSnapshotInput{SnapshotId: &s.snapshotId})
|
||||
if err != nil {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type VaultAWSEngineOptions,AssumeRoleConfig
|
||||
//go:generate mapstructure-to-hcl2 -type VaultAWSEngineOptions
|
||||
|
||||
package common
|
||||
|
||||
@@ -11,67 +11,15 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
awsCredentials "github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
|
||||
awsbase "github.com/hashicorp/aws-sdk-go-base"
|
||||
cleanhttp "github.com/hashicorp/go-cleanhttp"
|
||||
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
vaultapi "github.com/hashicorp/vault/api"
|
||||
)
|
||||
|
||||
// AssumeRoleConfig lets users set configuration options for assuming a special
|
||||
// role when executing Packer.
|
||||
//
|
||||
// Usage example:
|
||||
//
|
||||
// HCL config example:
|
||||
//
|
||||
// ```HCL
|
||||
// source "example" "amazon-ebs"{
|
||||
// assume_role {
|
||||
// role_arn = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
|
||||
// session_name = "SESSION_NAME"
|
||||
// external_id = "EXTERNAL_ID"
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// JSON config example:
|
||||
//
|
||||
// ```json
|
||||
// builder{
|
||||
// "type": "amazon-ebs",
|
||||
// "assume_role": {
|
||||
// "role_arn" : "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME",
|
||||
// "session_name": "SESSION_NAME",
|
||||
// "external_id" : "EXTERNAL_ID"
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
type AssumeRoleConfig struct {
|
||||
// Amazon Resource Name (ARN) of the IAM Role to assume.
|
||||
AssumeRoleARN string `mapstructure:"role_arn" required:"false"`
|
||||
// Number of seconds to restrict the assume role session duration.
|
||||
AssumeRoleDurationSeconds int `mapstructure:"duration_seconds" required:"false"`
|
||||
// The external ID to use when assuming the role. If omitted, no external
|
||||
// ID is passed to the AssumeRole call.
|
||||
AssumeRoleExternalID string `mapstructure:"external_id" required:"false"`
|
||||
// IAM Policy JSON describing further restricting permissions for the IAM
|
||||
// Role being assumed.
|
||||
AssumeRolePolicy string `mapstructure:"policy" required:"false"`
|
||||
// Set of Amazon Resource Names (ARNs) of IAM Policies describing further
|
||||
// restricting permissions for the IAM Role being
|
||||
AssumeRolePolicyARNs []string `mapstructure:"policy_arns" required:"false"`
|
||||
// Session name to use when assuming the role.
|
||||
AssumeRoleSessionName string `mapstructure:"session_name" required:"false"`
|
||||
// Map of assume role session tags.
|
||||
AssumeRoleTags map[string]string `mapstructure:"tags" required:"false"`
|
||||
// Set of assume role session tag keys to pass to any subsequent sessions.
|
||||
AssumeRoleTransitiveTagKeys []string `mapstructure:"transitive_tag_keys" required:"false"`
|
||||
}
|
||||
|
||||
type VaultAWSEngineOptions struct {
|
||||
Name string `mapstructure:"name"`
|
||||
RoleARN string `mapstructure:"role_arn"`
|
||||
@@ -96,21 +44,14 @@ 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"`
|
||||
// If provided with a role ARN, Packer will attempt to assume this role
|
||||
// using the supplied credentials. See
|
||||
// [AssumeRoleConfig](#assume-role-configuration) below for more
|
||||
// details on all of the options available, and for a usage example.
|
||||
AssumeRole AssumeRoleConfig `mapstructure:"assume_role" required:"false"`
|
||||
// This option is useful if you use a cloud
|
||||
// provider whose API is compatible with aws EC2. Specify another endpoint
|
||||
// like this https://ec2.custom.endpoint.com.
|
||||
CustomEndpointEc2 string `mapstructure:"custom_endpoint_ec2" required:"false"`
|
||||
// Path to a credentials file to load credentials from
|
||||
CredsFilename string `mapstructure:"shared_credentials_file" required:"false"`
|
||||
// Enable automatic decoding of any encoded authorization (error) messages
|
||||
// using the `sts:DecodeAuthorizationMessage` API. Note: requires that the
|
||||
// effective user/role have permissions to `sts:DecodeAuthorizationMessage`
|
||||
@@ -138,12 +79,13 @@ 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"`
|
||||
SkipMetadataApiCheck bool `mapstructure:"skip_metadata_api_check"`
|
||||
// Set to true if you want to skip validating AWS credentials before runtime.
|
||||
SkipCredsValidation bool `mapstructure:"skip_credential_validation"`
|
||||
SecretKey string `mapstructure:"secret_key" required:"true"`
|
||||
// Set to true if you want to skip
|
||||
// validation of the ami_regions configuration option. Default false.
|
||||
SkipValidation bool `mapstructure:"skip_region_validation" required:"false"`
|
||||
SkipMetadataApiCheck bool `mapstructure:"skip_metadata_api_check"`
|
||||
// The access token to use. This is different from the
|
||||
// access key and secret key. If you're not sure what this is, then you
|
||||
// probably don't need it. This will also be read from the AWS_SESSION_TOKEN
|
||||
@@ -153,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.
|
||||
@@ -174,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",
|
||||
@@ -185,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
|
||||
}
|
||||
@@ -210,13 +137,16 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
||||
return c.session, nil
|
||||
}
|
||||
|
||||
// Create new AWS config
|
||||
config := aws.NewConfig().WithCredentialsChainVerboseErrors(true)
|
||||
if c.MaxRetries > 0 {
|
||||
config = config.WithMaxRetries(c.MaxRetries)
|
||||
}
|
||||
|
||||
// Set AWS config defaults.
|
||||
staticCreds := credentials.NewStaticCredentials(c.AccessKey, c.SecretKey, c.Token)
|
||||
if _, err := staticCreds.Get(); err != credentials.ErrStaticCredentialsEmpty {
|
||||
config.WithCredentials(staticCreds)
|
||||
}
|
||||
|
||||
if c.RawRegion != "" {
|
||||
config = config.WithRegion(c.RawRegion)
|
||||
}
|
||||
@@ -234,16 +164,6 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
||||
}
|
||||
transport.Proxy = http.ProxyFromEnvironment
|
||||
|
||||
// Figure out which possible credential providers are valid; test that we
|
||||
// can get credentials via the selected providers, and set the providers in
|
||||
// the config.
|
||||
creds, err := c.GetCredentials(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.WithCredentials(creds)
|
||||
|
||||
// Create session options based on our AWS config
|
||||
opts := session.Options{
|
||||
SharedConfigState: session.SharedConfigEnable,
|
||||
Config: *config,
|
||||
@@ -268,8 +188,10 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
||||
|
||||
cp, err := c.session.Config.Credentials.Get()
|
||||
|
||||
if awserrors.Matches(err, "NoCredentialProviders", "") {
|
||||
return nil, c.NewNoValidCredentialSourcesError(err)
|
||||
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.html#specifying-amazon-credentials " +
|
||||
"for more information on providing credentials for the AWS Builder.")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -281,6 +203,7 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
||||
if c.DecodeAuthZMessages {
|
||||
DecodeAuthZMessages(c.session)
|
||||
}
|
||||
LogEnvOverrideWarnings()
|
||||
|
||||
return c.session, nil
|
||||
}
|
||||
@@ -300,42 +223,6 @@ func (c *AccessConfig) IsChinaCloud() bool {
|
||||
return strings.HasPrefix(c.SessionRegion(), "cn-")
|
||||
}
|
||||
|
||||
// GetCredentials gets credentials from the environment, shared credentials,
|
||||
// the session (which may include a credential process), or ECS/EC2 metadata
|
||||
// endpoints. GetCredentials also validates the credentials and the ability to
|
||||
// assume a role or will return an error if unsuccessful.
|
||||
func (c *AccessConfig) GetCredentials(config *aws.Config) (*awsCredentials.Credentials, error) {
|
||||
// Reload values into the config used by the Packer-Terraform shared SDK
|
||||
awsbaseConfig := &awsbase.Config{
|
||||
AccessKey: c.AccessKey,
|
||||
AssumeRoleARN: c.AssumeRole.AssumeRoleARN,
|
||||
AssumeRoleDurationSeconds: c.AssumeRole.AssumeRoleDurationSeconds,
|
||||
AssumeRoleExternalID: c.AssumeRole.AssumeRoleExternalID,
|
||||
AssumeRolePolicy: c.AssumeRole.AssumeRolePolicy,
|
||||
AssumeRolePolicyARNs: c.AssumeRole.AssumeRolePolicyARNs,
|
||||
AssumeRoleSessionName: c.AssumeRole.AssumeRoleSessionName,
|
||||
AssumeRoleTags: c.AssumeRole.AssumeRoleTags,
|
||||
AssumeRoleTransitiveTagKeys: c.AssumeRole.AssumeRoleTransitiveTagKeys,
|
||||
CredsFilename: c.CredsFilename,
|
||||
DebugLogging: false,
|
||||
// TODO: implement for Packer
|
||||
// IamEndpoint: c.Endpoints["iam"],
|
||||
Insecure: c.InsecureSkipTLSVerify,
|
||||
MaxRetries: c.MaxRetries,
|
||||
Profile: c.ProfileName,
|
||||
Region: c.RawRegion,
|
||||
SecretKey: c.SecretKey,
|
||||
SkipCredsValidation: c.SkipCredsValidation,
|
||||
SkipMetadataApiCheck: c.SkipMetadataApiCheck,
|
||||
// TODO: implement for Packer
|
||||
// SkipRequestingAccountId: c.SkipRequestingAccountId,
|
||||
// StsEndpoint: c.Endpoints["sts"],
|
||||
Token: c.Token,
|
||||
}
|
||||
|
||||
return awsbase.GetCredentials(awsbaseConfig)
|
||||
}
|
||||
|
||||
func (c *AccessConfig) GetCredsFromVault() error {
|
||||
// const EnvVaultAddress = "VAULT_ADDR"
|
||||
// const EnvVaultToken = "VAULT_TOKEN"
|
||||
@@ -369,7 +256,7 @@ func (c *AccessConfig) GetCredsFromVault() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AccessConfig) Prepare() []error {
|
||||
func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
var errs []error
|
||||
|
||||
if c.SkipMetadataApiCheck {
|
||||
@@ -397,27 +284,9 @@ func (c *AccessConfig) Prepare() []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()
|
||||
|
||||
// Default MaxRetries to 10, to make throttling issues less likely. The
|
||||
// Aws sdk defaults this to 3, which regularly gets tripped by users.
|
||||
if c.MaxRetries == 0 {
|
||||
c.MaxRetries = 10
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func (c *AccessConfig) NewNoValidCredentialSourcesError(err error) error {
|
||||
return fmt.Errorf("No valid credential sources found for AWS Builder. "+
|
||||
"Please see https://www.packer.io/docs/builders/amazon#authentication "+
|
||||
"for more information on providing credentials for the AWS Builder. "+
|
||||
"Error: %w", err)
|
||||
}
|
||||
|
||||
func (c *AccessConfig) NewEC2Connection() (ec2iface.EC2API, error) {
|
||||
if c.getEC2Connection != nil {
|
||||
return c.getEC2Connection(), nil
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// Code generated by "mapstructure-to-hcl2 -type VaultAWSEngineOptions,AssumeRoleConfig"; DO NOT EDIT.
|
||||
|
||||
// Code generated by "mapstructure-to-hcl2 -type VaultAWSEngineOptions"; DO NOT EDIT.
|
||||
package common
|
||||
|
||||
import (
|
||||
@@ -7,50 +6,13 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatAssumeRoleConfig is an auto-generated flat version of AssumeRoleConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatAssumeRoleConfig struct {
|
||||
AssumeRoleARN *string `mapstructure:"role_arn" required:"false" cty:"role_arn" hcl:"role_arn"`
|
||||
AssumeRoleDurationSeconds *int `mapstructure:"duration_seconds" required:"false" cty:"duration_seconds" hcl:"duration_seconds"`
|
||||
AssumeRoleExternalID *string `mapstructure:"external_id" required:"false" cty:"external_id" hcl:"external_id"`
|
||||
AssumeRolePolicy *string `mapstructure:"policy" required:"false" cty:"policy" hcl:"policy"`
|
||||
AssumeRolePolicyARNs []string `mapstructure:"policy_arns" required:"false" cty:"policy_arns" hcl:"policy_arns"`
|
||||
AssumeRoleSessionName *string `mapstructure:"session_name" required:"false" cty:"session_name" hcl:"session_name"`
|
||||
AssumeRoleTags map[string]string `mapstructure:"tags" required:"false" cty:"tags" hcl:"tags"`
|
||||
AssumeRoleTransitiveTagKeys []string `mapstructure:"transitive_tag_keys" required:"false" cty:"transitive_tag_keys" hcl:"transitive_tag_keys"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatAssumeRoleConfig.
|
||||
// FlatAssumeRoleConfig is an auto-generated flat version of AssumeRoleConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*AssumeRoleConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatAssumeRoleConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a AssumeRoleConfig.
|
||||
// This spec is used by HCL to read the fields of AssumeRoleConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatAssumeRoleConfig.
|
||||
func (*FlatAssumeRoleConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"role_arn": &hcldec.AttrSpec{Name: "role_arn", Type: cty.String, Required: false},
|
||||
"duration_seconds": &hcldec.AttrSpec{Name: "duration_seconds", Type: cty.Number, Required: false},
|
||||
"external_id": &hcldec.AttrSpec{Name: "external_id", Type: cty.String, Required: false},
|
||||
"policy": &hcldec.AttrSpec{Name: "policy", Type: cty.String, Required: false},
|
||||
"policy_arns": &hcldec.AttrSpec{Name: "policy_arns", Type: cty.List(cty.String), Required: false},
|
||||
"session_name": &hcldec.AttrSpec{Name: "session_name", Type: cty.String, Required: false},
|
||||
"tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false},
|
||||
"transitive_tag_keys": &hcldec.AttrSpec{Name: "transitive_tag_keys", Type: cty.List(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +36,20 @@ func TestAccessConfigPrepare_Region(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatalf("should have region validation err: %s", c.RawRegion)
|
||||
}
|
||||
|
||||
c.RawRegion = "custom"
|
||||
c.SkipValidation = true
|
||||
// testing whole prepare func here; this is checking that validation is
|
||||
// skipped, so we don't need a mock connection
|
||||
if err := c.Prepare(nil); err != nil {
|
||||
t.Fatalf("shouldn't have err: %s", err)
|
||||
}
|
||||
|
||||
c.SkipValidation = false
|
||||
c.RawRegion = ""
|
||||
if err := c.Prepare(nil); err != nil {
|
||||
t.Fatalf("shouldn't have err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccessConfigPrepare_RegionRestricted(t *testing.T) {
|
||||
@@ -47,7 +60,7 @@ func TestAccessConfigPrepare_RegionRestricted(t *testing.T) {
|
||||
Region: aws.String("us-gov-west-1"),
|
||||
}))
|
||||
|
||||
if err := c.Prepare(); err != nil {
|
||||
if err := c.Prepare(nil); err != nil {
|
||||
t.Fatalf("shouldn't have err: %s", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"log"
|
||||
"regexp"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// AMIConfig is for common configuration related to creating AMIs.
|
||||
@@ -16,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/legacy_json_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/legacy_json_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
|
||||
@@ -46,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/legacy_json_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/templates/hcl_templates/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
AMITag config.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.
|
||||
@@ -78,37 +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.
|
||||
//
|
||||
// Please note that if you are using an account with the global "Always
|
||||
// encrypt new EBS volumes" option set to `true`, Packer will be unable to
|
||||
// override this setting, and the final image will be encryoted whether
|
||||
// you set this value or not.
|
||||
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/`.
|
||||
@@ -135,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/legacy_json_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/templates/hcl_templates/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
SnapshotTag config.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
|
||||
@@ -169,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"))
|
||||
}
|
||||
@@ -220,15 +188,15 @@ 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))
|
||||
if !validateKmsKey(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 {
|
||||
@@ -294,7 +262,7 @@ func (c *AMIConfig) prepareRegions(accessConfig *AccessConfig) (errs []error) {
|
||||
}
|
||||
|
||||
// See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CopyImage.html
|
||||
func ValidateKmsKey(kmsKey string) (valid bool) {
|
||||
func validateKmsKey(kmsKey string) (valid bool) {
|
||||
kmsKeyIdPattern := `[a-f0-9-]+$`
|
||||
aliasPattern := `alias/[a-zA-Z0-9:/_-]+$`
|
||||
kmsArnStartPattern := `^arn:aws(-us-gov)?:kms:([a-z]{2}-(gov-)?[a-z]+-\d{1})?:(\d{12}):`
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
)
|
||||
|
||||
func testAMIConfig() *AMIConfig {
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
//go:generate struct-markdown
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
)
|
||||
|
||||
type AmiFilterOptions struct {
|
||||
// Filters used to select an AMI. Any filter described in the docs for
|
||||
// [DescribeImages](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeImages.html)
|
||||
// is valid.
|
||||
Filters map[string]string `mapstructure:"filters"`
|
||||
// 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.
|
||||
Owners []string `mapstructure:"owners"`
|
||||
// Selects the newest created image when true.
|
||||
// This is most useful for selecting a daily distro build.
|
||||
MostRecent bool `mapstructure:"most_recent"`
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) GetOwners() []*string {
|
||||
res := make([]*string, 0, len(d.Owners))
|
||||
for _, owner := range d.Owners {
|
||||
i := owner
|
||||
res = append(res, &i)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) Empty() bool {
|
||||
return len(d.Owners) == 0 && len(d.Filters) == 0
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) NoOwner() bool {
|
||||
return len(d.Owners) == 0
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) GetFilteredImage(params *ec2.DescribeImagesInput, ec2conn *ec2.EC2) (*ec2.Image, error) {
|
||||
// We have filters to apply
|
||||
if len(d.Filters) > 0 {
|
||||
params.Filters = buildEc2Filters(d.Filters)
|
||||
}
|
||||
if len(d.Owners) > 0 {
|
||||
params.Owners = d.GetOwners()
|
||||
}
|
||||
|
||||
log.Printf("Using AMI Filters %v", params)
|
||||
imageResp, err := ec2conn.DescribeImages(params)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error querying AMI: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(imageResp.Images) == 0 {
|
||||
err := fmt.Errorf("No AMI was found matching filters: %v", params)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(imageResp.Images) > 1 && !d.MostRecent {
|
||||
err := fmt.Errorf("Your query returned more than one result. Please try a more specific search, or set most_recent to true.")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var image *ec2.Image
|
||||
if d.MostRecent {
|
||||
image = mostRecentAmi(imageResp.Images)
|
||||
} else {
|
||||
image = imageResp.Images[0]
|
||||
}
|
||||
return image, nil
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// Artifact is an artifact implementation that contains built AMIs.
|
||||
@@ -103,7 +103,7 @@ func (a *Artifact) Destroy() error {
|
||||
if len(errors) == 1 {
|
||||
return errors[0]
|
||||
} else {
|
||||
return &packersdk.MultiError{Errors: errors}
|
||||
return &packer.MultiError{Errors: errors}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func TestArtifact_Impl(t *testing.T) {
|
||||
var _ packersdk.Artifact = new(Artifact)
|
||||
var _ packer.Artifact = new(Artifact)
|
||||
}
|
||||
|
||||
func TestArtifactId(t *testing.T) {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package awserrors
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
)
|
||||
|
||||
// Returns true if the err matches all these conditions:
|
||||
// * err is of type awserr.Error
|
||||
// * Error.Code() matches code
|
||||
// * Error.Message() contains message
|
||||
func Matches(err error, code string, message string) bool {
|
||||
if err, ok := err.(awserr.Error); ok {
|
||||
return err.Code() == code && strings.Contains(err.Message(), message)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -9,20 +9,11 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
const (
|
||||
minIops = 100
|
||||
maxIops = 64000
|
||||
minIopsGp3 = 3000
|
||||
maxIopsGp3 = 16000
|
||||
minThroughput = 125
|
||||
maxThroughput = 1000
|
||||
)
|
||||
|
||||
// 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:
|
||||
@@ -30,31 +21,14 @@ const (
|
||||
// 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
|
||||
//
|
||||
@@ -76,35 +50,28 @@ type BlockDevice struct {
|
||||
// See the documentation on
|
||||
// [IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html)
|
||||
// for more information
|
||||
IOPS *int64 `mapstructure:"iops" required:"false"`
|
||||
IOPS int64 `mapstructure:"iops" required:"false"`
|
||||
// Suppresses the specified device included in the block device mapping of
|
||||
// the AMI.
|
||||
NoDevice bool `mapstructure:"no_device" required:"false"`
|
||||
// The ID of the snapshot.
|
||||
SnapshotId string `mapstructure:"snapshot_id" required:"false"`
|
||||
// The throughput for gp3 volumes, only valid for gp3 types
|
||||
// See the documentation on
|
||||
// [Throughput](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html)
|
||||
// for more information
|
||||
Throughput *int64 `mapstructure:"throughput" required:"false"`
|
||||
// The virtual device name. See the documentation on Block Device Mapping
|
||||
// for more information.
|
||||
VirtualName string `mapstructure:"virtual_name" required:"false"`
|
||||
// The volume type. gp2 & gp3 for General Purpose (SSD) volumes, io1 & io2
|
||||
// for Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD,
|
||||
// sc1 for Cold HDD, and standard for Magnetic volumes.
|
||||
// The volume type. gp2 for General Purpose (SSD) volumes, io1 for
|
||||
// Provisioned IOPS (SSD) volumes, st1 for Throughput Optimized HDD, sc1
|
||||
// for Cold HDD, and standard for Magnetic volumes.
|
||||
VolumeType string `mapstructure:"volume_type" required:"false"`
|
||||
// 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"`
|
||||
}
|
||||
@@ -148,14 +115,9 @@ func (blockDevice BlockDevice) BuildEC2BlockDeviceMapping() *ec2.BlockDeviceMapp
|
||||
ebsBlockDevice.VolumeSize = aws.Int64(blockDevice.VolumeSize)
|
||||
}
|
||||
|
||||
switch blockDevice.VolumeType {
|
||||
case "io1", "io2", "gp3":
|
||||
ebsBlockDevice.Iops = blockDevice.IOPS
|
||||
}
|
||||
|
||||
// Throughput is only valid for gp3 types
|
||||
if blockDevice.VolumeType == "gp3" {
|
||||
ebsBlockDevice.Throughput = blockDevice.Throughput
|
||||
// IOPS is only valid for io1 type
|
||||
if blockDevice.VolumeType == "io1" {
|
||||
ebsBlockDevice.Iops = aws.Int64(blockDevice.IOPS)
|
||||
}
|
||||
|
||||
// You cannot specify Encrypted if you specify a Snapshot ID
|
||||
@@ -173,11 +135,6 @@ func (blockDevice BlockDevice) BuildEC2BlockDeviceMapping() *ec2.BlockDeviceMapp
|
||||
return mapping
|
||||
}
|
||||
|
||||
var iopsRatios = map[string]int64{
|
||||
"io1": 50,
|
||||
"io2": 500,
|
||||
}
|
||||
|
||||
func (b *BlockDevice) Prepare(ctx *interpolate.Context) error {
|
||||
if b.DeviceName == "" {
|
||||
return fmt.Errorf("The `device_name` must be specified " +
|
||||
@@ -190,33 +147,6 @@ func (b *BlockDevice) Prepare(ctx *interpolate.Context) error {
|
||||
"true` when setting a kms_key_id.", b.DeviceName)
|
||||
}
|
||||
|
||||
if ratio, ok := iopsRatios[b.VolumeType]; b.VolumeSize != 0 && ok {
|
||||
if b.IOPS != nil && (*b.IOPS/b.VolumeSize > ratio) {
|
||||
return fmt.Errorf("%s: the maximum ratio of provisioned IOPS to requested volume size "+
|
||||
"(in GiB) is %v:1 for %s volumes", b.DeviceName, ratio, b.VolumeType)
|
||||
}
|
||||
|
||||
if b.IOPS != nil && (*b.IOPS < minIops || *b.IOPS > maxIops) {
|
||||
return fmt.Errorf("IOPS must be between %d and %d for device %s",
|
||||
minIops, maxIops, b.DeviceName)
|
||||
}
|
||||
}
|
||||
|
||||
if b.VolumeType == "gp3" {
|
||||
if b.Throughput != nil && (*b.Throughput < minThroughput || *b.Throughput > maxThroughput) {
|
||||
return fmt.Errorf("Throughput must be between %d and %d for device %s",
|
||||
minThroughput, maxThroughput, b.DeviceName)
|
||||
}
|
||||
|
||||
if b.IOPS != nil && (*b.IOPS < minIopsGp3 || *b.IOPS > maxIopsGp3) {
|
||||
return fmt.Errorf("IOPS must be between %d and %d for device %s",
|
||||
minIopsGp3, maxIopsGp3, b.DeviceName)
|
||||
}
|
||||
} else if b.Throughput != nil {
|
||||
return fmt.Errorf("Throughput is not available for device %s",
|
||||
b.DeviceName)
|
||||
}
|
||||
|
||||
_, err := interpolate.RenderInterface(&b, ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// Code generated by "mapstructure-to-hcl2 -type BlockDevice"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
@@ -10,17 +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"`
|
||||
Throughput *int64 `mapstructure:"throughput" required:"false" cty:"throughput" hcl:"throughput"`
|
||||
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.
|
||||
@@ -41,7 +39,6 @@ func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
|
||||
"iops": &hcldec.AttrSpec{Name: "iops", Type: cty.Number, Required: false},
|
||||
"no_device": &hcldec.AttrSpec{Name: "no_device", Type: cty.Bool, Required: false},
|
||||
"snapshot_id": &hcldec.AttrSpec{Name: "snapshot_id", Type: cty.String, Required: false},
|
||||
"throughput": &hcldec.AttrSpec{Name: "throughput", Type: cty.Number, Required: false},
|
||||
"virtual_name": &hcldec.AttrSpec{Name: "virtual_name", Type: cty.String, Required: false},
|
||||
"volume_type": &hcldec.AttrSpec{Name: "volume_type", Type: cty.String, Required: false},
|
||||
"volume_size": &hcldec.AttrSpec{Name: "volume_size", Type: cty.Number, Required: false},
|
||||
|
||||
@@ -6,8 +6,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
)
|
||||
|
||||
func TestBlockDevice(t *testing.T) {
|
||||
@@ -54,7 +53,7 @@ func TestBlockDevice(t *testing.T) {
|
||||
VolumeType: "io1",
|
||||
VolumeSize: 8,
|
||||
DeleteOnTermination: true,
|
||||
IOPS: aws.Int64(1000),
|
||||
IOPS: 1000,
|
||||
},
|
||||
|
||||
Result: &ec2.BlockDeviceMapping{
|
||||
@@ -67,25 +66,6 @@ func TestBlockDevice(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnTermination: true,
|
||||
IOPS: aws.Int64(1000),
|
||||
},
|
||||
|
||||
Result: &ec2.BlockDeviceMapping{
|
||||
DeviceName: aws.String("/dev/sdb"),
|
||||
Ebs: &ec2.EbsBlockDevice{
|
||||
VolumeType: aws.String("io2"),
|
||||
VolumeSize: aws.Int64(8),
|
||||
DeleteOnTermination: aws.Bool(true),
|
||||
Iops: aws.Int64(1000),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
@@ -163,29 +143,6 @@ func TestBlockDevice(t *testing.T) {
|
||||
NoDevice: aws.String(""),
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp3",
|
||||
VolumeSize: 8,
|
||||
Throughput: aws.Int64(125),
|
||||
IOPS: aws.Int64(3000),
|
||||
DeleteOnTermination: true,
|
||||
Encrypted: config.TriTrue,
|
||||
},
|
||||
|
||||
Result: &ec2.BlockDeviceMapping{
|
||||
DeviceName: aws.String("/dev/sdb"),
|
||||
Ebs: &ec2.EbsBlockDevice{
|
||||
VolumeType: aws.String("gp3"),
|
||||
VolumeSize: aws.Int64(8),
|
||||
Throughput: aws.Int64(125),
|
||||
Iops: aws.Int64(3000),
|
||||
DeleteOnTermination: aws.Bool(true),
|
||||
Encrypted: aws.Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
@@ -206,196 +163,3 @@ func TestBlockDevice(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIOPSValidation(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
device BlockDevice
|
||||
ok bool
|
||||
msg string
|
||||
}{
|
||||
// volume size unknown
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io1",
|
||||
IOPS: aws.Int64(1000),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io2",
|
||||
IOPS: aws.Int64(1000),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
// ratio requirement satisfied
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io1",
|
||||
VolumeSize: 50,
|
||||
IOPS: aws.Int64(1000),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io2",
|
||||
VolumeSize: 100,
|
||||
IOPS: aws.Int64(1000),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
// ratio requirement not satisfied
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io1",
|
||||
VolumeSize: 10,
|
||||
IOPS: aws.Int64(2000),
|
||||
},
|
||||
ok: false,
|
||||
msg: "/dev/sdb: the maximum ratio of provisioned IOPS to requested volume size (in GiB) is 50:1 for io1 volumes",
|
||||
},
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io2",
|
||||
VolumeSize: 50,
|
||||
IOPS: aws.Int64(30000),
|
||||
},
|
||||
ok: false,
|
||||
msg: "/dev/sdb: the maximum ratio of provisioned IOPS to requested volume size (in GiB) is 500:1 for io2 volumes",
|
||||
},
|
||||
// exceed max iops
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io2",
|
||||
VolumeSize: 500,
|
||||
IOPS: aws.Int64(99999),
|
||||
},
|
||||
ok: false,
|
||||
msg: "IOPS must be between 100 and 64000 for device /dev/sdb",
|
||||
},
|
||||
// lower than min iops
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io2",
|
||||
VolumeSize: 50,
|
||||
IOPS: aws.Int64(10),
|
||||
},
|
||||
ok: false,
|
||||
msg: "IOPS must be between 100 and 64000 for device /dev/sdb",
|
||||
},
|
||||
// exceed max iops
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp3",
|
||||
VolumeSize: 50,
|
||||
Throughput: aws.Int64(125),
|
||||
IOPS: aws.Int64(99999),
|
||||
},
|
||||
ok: false,
|
||||
msg: "IOPS must be between 3000 and 16000 for device /dev/sdb",
|
||||
},
|
||||
// lower than min iops
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp3",
|
||||
VolumeSize: 50,
|
||||
Throughput: aws.Int64(125),
|
||||
IOPS: aws.Int64(10),
|
||||
},
|
||||
ok: false,
|
||||
msg: "IOPS must be between 3000 and 16000 for device /dev/sdb",
|
||||
},
|
||||
}
|
||||
|
||||
ctx := interpolate.Context{}
|
||||
for _, testCase := range cases {
|
||||
err := testCase.device.Prepare(&ctx)
|
||||
if testCase.ok && err != nil {
|
||||
t.Fatalf("should not error, but: %v", err)
|
||||
}
|
||||
if !testCase.ok {
|
||||
if err == nil {
|
||||
t.Fatalf("should error")
|
||||
} else if err.Error() != testCase.msg {
|
||||
t.Fatalf("wrong error: expected %s, found: %v", testCase.msg, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestThroughputValidation(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
device BlockDevice
|
||||
ok bool
|
||||
msg string
|
||||
}{
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp3",
|
||||
Throughput: aws.Int64(125),
|
||||
IOPS: aws.Int64(3000),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp3",
|
||||
Throughput: aws.Int64(1000),
|
||||
IOPS: aws.Int64(3000),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
// exceed max Throughput
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp3",
|
||||
Throughput: aws.Int64(1001),
|
||||
IOPS: aws.Int64(3000),
|
||||
},
|
||||
ok: false,
|
||||
msg: "Throughput must be between 125 and 1000 for device /dev/sdb",
|
||||
},
|
||||
// lower than min Throughput
|
||||
{
|
||||
device: BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp3",
|
||||
Throughput: aws.Int64(124),
|
||||
IOPS: aws.Int64(3000),
|
||||
},
|
||||
ok: false,
|
||||
msg: "Throughput must be between 125 and 1000 for device /dev/sdb",
|
||||
},
|
||||
}
|
||||
|
||||
ctx := interpolate.Context{}
|
||||
for _, testCase := range cases {
|
||||
err := testCase.device.Prepare(&ctx)
|
||||
if testCase.ok && err != nil {
|
||||
t.Fatalf("should not error, but: %v", err)
|
||||
}
|
||||
if !testCase.ok {
|
||||
if err == nil {
|
||||
t.Fatalf("should error")
|
||||
} else if err.Error() != testCase.msg {
|
||||
t.Fatalf("wrong error: expected %s, found: %v", testCase.msg, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/retry"
|
||||
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
|
||||
"github.com/hashicorp/packer/common/retry"
|
||||
)
|
||||
|
||||
// DestroyAMIs deregisters the AWS machine images in imageids from an active AWS account
|
||||
@@ -30,7 +31,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error {
|
||||
err = retry.Config{
|
||||
Tries: 11,
|
||||
ShouldRetry: func(err error) bool {
|
||||
return awserrors.Matches(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 {
|
||||
@@ -53,7 +54,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error {
|
||||
err = retry.Config{
|
||||
Tries: 11,
|
||||
ShouldRetry: func(err error) bool {
|
||||
return awserrors.Matches(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 {
|
||||
@@ -73,3 +74,14 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns true if the error matches all these conditions:
|
||||
// * err is of type awserr.Error
|
||||
// * Error.Code() matches code
|
||||
// * Error.Message() contains message
|
||||
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)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -3,21 +3,20 @@ package common
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/packerbuilderdata"
|
||||
"github.com/hashicorp/packer/builder"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
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 *packerbuilderdata.GeneratedData) *BuildInfoTemplate {
|
||||
func extractBuildInfo(region string, state multistep.StateBag, generatedData *builder.GeneratedData) *BuildInfoTemplate {
|
||||
rawSourceAMI, hasSourceAMI := state.GetOk("source_image")
|
||||
if !hasSourceAMI {
|
||||
return &BuildInfoTemplate{
|
||||
@@ -32,32 +31,13 @@ func extractBuildInfo(region string, state multistep.StateBag, generatedData *pa
|
||||
}
|
||||
|
||||
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",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,16 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/packerbuilderdata"
|
||||
"github.com/hashicorp/packer/builder"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
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"),
|
||||
RootDeviceType: aws.String("ebs"),
|
||||
Tags: []*ec2.Tag{
|
||||
{
|
||||
Key: aws.String("key-1"),
|
||||
@@ -36,8 +34,8 @@ func testState() multistep.StateBag {
|
||||
return state
|
||||
}
|
||||
|
||||
func testGeneratedData(state multistep.StateBag) packerbuilderdata.GeneratedData {
|
||||
generatedData := packerbuilderdata.GeneratedData{State: state}
|
||||
func testGeneratedData(state multistep.StateBag) builder.GeneratedData {
|
||||
generatedData := builder.GeneratedData{State: state}
|
||||
return generatedData
|
||||
}
|
||||
|
||||
@@ -61,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",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type AmiFilterOptions,SecurityGroupFilterOptions,SubnetFilterOptions,VpcFilterOptions,PolicyDocument,Statement,MetadataOptions
|
||||
//go:generate mapstructure-to-hcl2 -type AmiFilterOptions,SecurityGroupFilterOptions,SubnetFilterOptions,VpcFilterOptions,PolicyDocument,Statement
|
||||
|
||||
package common
|
||||
|
||||
@@ -11,51 +11,71 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
var reShutdownBehavior = regexp.MustCompile("^(stop|terminate)$")
|
||||
|
||||
type AmiFilterOptions struct {
|
||||
Filters map[string]string
|
||||
Owners []string
|
||||
MostRecent bool `mapstructure:"most_recent"`
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) GetOwners() []*string {
|
||||
res := make([]*string, 0, len(d.Owners))
|
||||
for _, owner := range d.Owners {
|
||||
i := owner
|
||||
res = append(res, &i)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) Empty() bool {
|
||||
return len(d.Owners) == 0 && len(d.Filters) == 0
|
||||
}
|
||||
|
||||
func (d *AmiFilterOptions) NoOwner() bool {
|
||||
return len(d.Owners) == 0
|
||||
}
|
||||
|
||||
type SubnetFilterOptions struct {
|
||||
config.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 {
|
||||
config.NameValueFilter `mapstructure:",squash"`
|
||||
Filters map[string]string
|
||||
}
|
||||
|
||||
type Statement struct {
|
||||
Effect string `mapstructure:"Effect" required:"false"`
|
||||
Action []string `mapstructure:"Action" required:"false"`
|
||||
Resource []string `mapstructure:"Resource" required:"false"`
|
||||
Effect string
|
||||
Action []string
|
||||
Resource string
|
||||
}
|
||||
|
||||
type PolicyDocument struct {
|
||||
Version string `mapstructure:"Version" required:"false"`
|
||||
Statement []Statement `mapstructure:"Statement" required:"false"`
|
||||
Version string
|
||||
Statement []Statement
|
||||
}
|
||||
|
||||
func (d *VpcFilterOptions) Empty() bool {
|
||||
return len(d.Filters) == 0
|
||||
}
|
||||
|
||||
type SecurityGroupFilterOptions struct {
|
||||
config.NameValueFilter `mapstructure:",squash"`
|
||||
Filters map[string]string
|
||||
}
|
||||
|
||||
// Configures the metadata options.
|
||||
// See [Configure IMDS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) for details.
|
||||
type MetadataOptions struct {
|
||||
// A string to enable or disble the IMDS endpoint for an instance. Defaults to enabled.
|
||||
// Accepts either "enabled" or "disabled"
|
||||
HttpEndpoint string `mapstructure:"http_endpoint" required:"false"`
|
||||
// A string to either set the use of IMDSv2 for the instance to optional or required. Defaults to "optional".
|
||||
// Accepts either "optional" or "required"
|
||||
HttpTokens string `mapstructure:"http_tokens" required:"false"`
|
||||
// A numerical value to set an upper limit for the amount of hops allowed when communicating with IMDS endpoints.
|
||||
// Defaults to 1.
|
||||
HttpPutResponseHopLimit int64 `mapstructure:"http_put_response_hop_limit" required:"false"`
|
||||
func (d *SecurityGroupFilterOptions) Empty() bool {
|
||||
return len(d.Filters) == 0
|
||||
}
|
||||
|
||||
// RunConfig contains configuration for running an instance from a source
|
||||
@@ -76,27 +96,23 @@ type RunConfig struct {
|
||||
BlockDurationMinutes int64 `mapstructure:"block_duration_minutes" required:"false"`
|
||||
// Packer normally stops the build instance after all provisioners have
|
||||
// run. For Windows instances, it is sometimes desirable to [run
|
||||
// Sysprep](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/Creating_EBSbacked_WinAMI.html)
|
||||
// Sysprep](http://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ami-create-standard.html)
|
||||
// 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).
|
||||
@@ -157,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": {
|
||||
@@ -169,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
|
||||
@@ -188,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/legacy_json_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/templates/hcl_templates/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
RunTag config.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.
|
||||
@@ -210,42 +210,25 @@ type RunConfig struct {
|
||||
SecurityGroupIds []string `mapstructure:"security_group_ids" required:"false"`
|
||||
// The source AMI whose root volume will be copied and
|
||||
// provisioned on the currently running instance. This must be an EBS-backed
|
||||
// AMI with a root volume snapshot that you have access to.
|
||||
// AMI with a root volume snapshot that you have access to. Note: this is not
|
||||
// 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,
|
||||
@@ -303,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/templates/hcl_templates/expressions#dynamic-blocks)
|
||||
// will allow you to create those programatically.
|
||||
SpotTag config.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"
|
||||
@@ -327,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
|
||||
@@ -366,12 +328,10 @@ type RunConfig struct {
|
||||
// subnet-12345def, where Packer will launch the EC2 instance. This field is
|
||||
// required if you are using an non-default VPC.
|
||||
SubnetId string `mapstructure:"subnet_id" required:"false"`
|
||||
// [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used
|
||||
// when Packer launches the EC2 instance, allowing it to be launched on dedicated hardware.
|
||||
//
|
||||
// The default is "default", meaning shared tenancy. Allowed values are "default",
|
||||
// "dedicated" and "host".
|
||||
Tenancy string `mapstructure:"tenancy" required:"false"`
|
||||
// The name of the temporary key pair to
|
||||
// generate. By default, Packer generates a name that looks like
|
||||
// `packer_<UUID>`, where <UUID> is a 36 character unique identifier.
|
||||
TemporaryKeyPairName string `mapstructure:"temporary_key_pair_name" required:"false"`
|
||||
// A list of IPv4 CIDR blocks to be authorized access to the instance, when
|
||||
// packer is creating a temporary security group.
|
||||
//
|
||||
@@ -388,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"
|
||||
@@ -440,14 +384,11 @@ type RunConfig struct {
|
||||
// 10m
|
||||
WindowsPasswordTimeout time.Duration `mapstructure:"windows_password_timeout" required:"false"`
|
||||
|
||||
// [Metadata Settings](#metadata-settings)
|
||||
Metadata MetadataOptions `mapstructure:"metadata_options" required:"false"`
|
||||
|
||||
// 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
|
||||
@@ -457,28 +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"`
|
||||
|
||||
// The time to wait before establishing the Session Manager session.
|
||||
// The value of this should be a duration. Examples are
|
||||
// `5s` and `1m30s` which will cause Packer to wait five seconds and one
|
||||
// minute 30 seconds, respectively. If no set, defaults to 10 seconds.
|
||||
// This option is useful when the remote port takes longer to become available.
|
||||
PauseBeforeSSM time.Duration `mapstructure:"pause_before_ssm"`
|
||||
|
||||
// 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 {
|
||||
@@ -503,68 +423,15 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
// Validation
|
||||
errs := c.Comm.Prepare(ctx)
|
||||
|
||||
if c.Metadata.HttpEndpoint == "" {
|
||||
c.Metadata.HttpEndpoint = "enabled"
|
||||
}
|
||||
|
||||
if c.Metadata.HttpTokens == "" {
|
||||
c.Metadata.HttpTokens = "optional"
|
||||
}
|
||||
|
||||
if c.Metadata.HttpPutResponseHopLimit == 0 {
|
||||
c.Metadata.HttpPutResponseHopLimit = 1
|
||||
}
|
||||
|
||||
if c.Metadata.HttpEndpoint != "enabled" && c.Metadata.HttpEndpoint != "disabled" {
|
||||
msg := fmt.Errorf("http_endpoint requires either disabled or enabled as its value")
|
||||
errs = append(errs, msg)
|
||||
}
|
||||
|
||||
if c.Metadata.HttpTokens != "optional" && c.Metadata.HttpTokens != "required" {
|
||||
msg := fmt.Errorf("http_tokens requires either optional or required as its value")
|
||||
errs = append(errs, msg)
|
||||
}
|
||||
|
||||
if c.Metadata.HttpPutResponseHopLimit < 1 || c.Metadata.HttpPutResponseHopLimit > 64 {
|
||||
msg := fmt.Errorf("http_put_response_hop_limit requires a number between 1 and 64")
|
||||
errs = append(errs, msg)
|
||||
}
|
||||
|
||||
// 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.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."))
|
||||
@@ -638,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 {
|
||||
@@ -648,21 +515,9 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
}
|
||||
}
|
||||
|
||||
if c.Tenancy != "" &&
|
||||
c.Tenancy != "default" &&
|
||||
c.Tenancy != "dedicated" &&
|
||||
c.Tenancy != "host" {
|
||||
errs = append(errs, fmt.Errorf("Error: Unknown tenancy type %s", c.Tenancy))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
// Code generated by "mapstructure-to-hcl2 -type AmiFilterOptions,SecurityGroupFilterOptions,SubnetFilterOptions,VpcFilterOptions,PolicyDocument,Statement,MetadataOptions"; DO NOT EDIT.
|
||||
|
||||
// Code generated by "mapstructure-to-hcl2 -type AmiFilterOptions,SecurityGroupFilterOptions,SubnetFilterOptions,VpcFilterOptions,PolicyDocument,Statement"; DO NOT EDIT.
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"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 `mapstructure:"filters" cty:"filters" hcl:"filters"`
|
||||
Owners []string `mapstructure:"owners" 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,45 +26,18 @@ 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},
|
||||
"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},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatMetadataOptions is an auto-generated flat version of MetadataOptions.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatMetadataOptions struct {
|
||||
HttpEndpoint *string `mapstructure:"http_endpoint" required:"false" cty:"http_endpoint" hcl:"http_endpoint"`
|
||||
HttpTokens *string `mapstructure:"http_tokens" required:"false" cty:"http_tokens" hcl:"http_tokens"`
|
||||
HttpPutResponseHopLimit *int64 `mapstructure:"http_put_response_hop_limit" required:"false" cty:"http_put_response_hop_limit" hcl:"http_put_response_hop_limit"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatMetadataOptions.
|
||||
// FlatMetadataOptions is an auto-generated flat version of MetadataOptions.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*MetadataOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatMetadataOptions)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a MetadataOptions.
|
||||
// This spec is used by HCL to read the fields of MetadataOptions.
|
||||
// The decoded values from this spec will then be applied to a FlatMetadataOptions.
|
||||
func (*FlatMetadataOptions) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"http_endpoint": &hcldec.AttrSpec{Name: "http_endpoint", Type: cty.String, Required: false},
|
||||
"http_tokens": &hcldec.AttrSpec{Name: "http_tokens", Type: cty.String, Required: false},
|
||||
"http_put_response_hop_limit": &hcldec.AttrSpec{Name: "http_put_response_hop_limit", Type: cty.Number, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 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 `mapstructure:"Version" required:"false" cty:"Version" hcl:"Version"`
|
||||
Statement []FlatStatement `mapstructure:"Statement" required:"false" cty:"Statement" hcl:"Statement"`
|
||||
Version *string `cty:"version"`
|
||||
Statement []FlatStatement `cty:"statement"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatPolicyDocument.
|
||||
@@ -81,8 +52,8 @@ func (*PolicyDocument) FlatMapstructure() interface{ HCL2Spec() map[string]hclde
|
||||
// The decoded values from this spec will then be applied to a FlatPolicyDocument.
|
||||
func (*FlatPolicyDocument) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"Version": &hcldec.AttrSpec{Name: "Version", Type: cty.String, Required: false},
|
||||
"Statement": &hcldec.BlockListSpec{TypeName: "Statement", Nested: hcldec.ObjectSpec((*FlatStatement)(nil).HCL2Spec())},
|
||||
"version": &hcldec.AttrSpec{Name: "version", Type: cty.String, Required: false},
|
||||
"statement": &hcldec.BlockListSpec{TypeName: "statement", Nested: hcldec.ObjectSpec((*FlatStatement)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -90,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 []config.FlatNameValue `cty:"filter" hcl:"filter"`
|
||||
Filters map[string]string `cty:"filters"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatSecurityGroupFilterOptions.
|
||||
@@ -106,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((*config.FlatNameValue)(nil).HCL2Spec())},
|
||||
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -115,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 `mapstructure:"Effect" required:"false" cty:"Effect" hcl:"Effect"`
|
||||
Action []string `mapstructure:"Action" required:"false" cty:"Action" hcl:"Action"`
|
||||
Resource []string `mapstructure:"Resource" required:"false" cty:"Resource" hcl:"Resource"`
|
||||
Effect *string `cty:"effect"`
|
||||
Action []string `cty:"action"`
|
||||
Resource *string `cty:"resource"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatStatement.
|
||||
@@ -132,9 +101,9 @@ func (*Statement) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spe
|
||||
// The decoded values from this spec will then be applied to a FlatStatement.
|
||||
func (*FlatStatement) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"Effect": &hcldec.AttrSpec{Name: "Effect", Type: cty.String, Required: false},
|
||||
"Action": &hcldec.AttrSpec{Name: "Action", Type: cty.List(cty.String), Required: false},
|
||||
"Resource": &hcldec.AttrSpec{Name: "Resource", Type: cty.List(cty.String), Required: false},
|
||||
"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.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -142,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 []config.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.
|
||||
@@ -160,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((*config.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},
|
||||
}
|
||||
@@ -171,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 []config.FlatNameValue `cty:"filter" hcl:"filter"`
|
||||
Filters map[string]string `cty:"filters"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatVpcFilterOptions.
|
||||
@@ -187,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((*config.FlatNameValue)(nil).HCL2Spec())},
|
||||
"filters": &hcldec.BlockAttrsSpec{TypeName: "filters", ElementType: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -73,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)")
|
||||
}
|
||||
@@ -84,10 +84,7 @@ func TestRunConfigPrepare_SourceAmiFilterGood(t *testing.T) {
|
||||
owner := "123"
|
||||
filter_key := "name"
|
||||
filter_value := "foo"
|
||||
goodFilter := AmiFilterOptions{
|
||||
Owners: []string{owner},
|
||||
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)
|
||||
@@ -229,23 +226,3 @@ func TestRunConfigPrepare_TemporaryKeyPairName(t *testing.T) {
|
||||
t.Fatal("keypair name does not match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_TenancyBad(t *testing.T) {
|
||||
c := testConfig()
|
||||
c.Tenancy = "not_real"
|
||||
|
||||
if err := c.Prepare(nil); len(err) != 1 {
|
||||
t.Fatal("Should error if tenancy is set to an invalid type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_TenancyGood(t *testing.T) {
|
||||
validTenancy := []string{"", "default", "dedicated", "host"}
|
||||
for _, vt := range validTenancy {
|
||||
c := testConfig()
|
||||
c.Tenancy = vt
|
||||
if err := c.Prepare(nil); len(err) != 0 {
|
||||
t.Fatalf("Should not error if tenancy is set to %s", vt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
type ec2Describer interface {
|
||||
@@ -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
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -13,7 +13,6 @@ const (
|
||||
publicIP = "192.168.1.1"
|
||||
privateDNS = "private.dns.test"
|
||||
publicDNS = "public.dns.test"
|
||||
localhost = "localhost"
|
||||
sshHostTemplate = "custom.host.value"
|
||||
)
|
||||
|
||||
@@ -33,13 +32,11 @@ func TestSSHHost(t *testing.T) {
|
||||
}{
|
||||
{1, "", "", true, publicDNS, ""},
|
||||
{1, "", "private_ip", true, privateIP, ""},
|
||||
{1, "", "session_manager", true, localhost, ""},
|
||||
{1, "vpc-id", "", true, publicIP, ""},
|
||||
{1, "vpc-id", "private_ip", true, privateIP, ""},
|
||||
{1, "vpc-id", "private_dns", true, privateDNS, ""},
|
||||
{1, "vpc-id", "public_dns", true, publicDNS, ""},
|
||||
{1, "vpc-id", "public_ip", true, publicIP, ""},
|
||||
{1, "vpc-id", "session_manager", true, localhost, ""},
|
||||
{2, "", "", true, publicDNS, ""},
|
||||
{2, "", "private_ip", true, privateIP, ""},
|
||||
{2, "vpc-id", "", true, publicIP, ""},
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
package ssm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"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"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/retry"
|
||||
"github.com/hashicorp/packer-plugin-sdk/shell-local/localexec"
|
||||
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
SvcClient ssmiface.SSMAPI
|
||||
Region string
|
||||
InstanceID string
|
||||
LocalPort, RemotePort int
|
||||
}
|
||||
|
||||
func (s Session) buildTunnelInput() *ssm.StartSessionInput {
|
||||
portNumber, localPortNumber := strconv.Itoa(s.RemotePort), strconv.Itoa(s.LocalPort)
|
||||
params := map[string][]*string{
|
||||
"portNumber": []*string{aws.String(portNumber)},
|
||||
"localPortNumber": []*string{aws.String(localPortNumber)},
|
||||
}
|
||||
|
||||
return &ssm.StartSessionInput{
|
||||
DocumentName: aws.String("AWS-StartPortForwardingSession"),
|
||||
Parameters: params,
|
||||
Target: aws.String(s.InstanceID),
|
||||
}
|
||||
}
|
||||
|
||||
// getCommand return a valid ordered set of arguments to pass to the driver command.
|
||||
func (s Session) getCommand(ctx context.Context) ([]string, string, error) {
|
||||
input := s.buildTunnelInput()
|
||||
|
||||
var session *ssm.StartSessionOutput
|
||||
err := retry.Config{
|
||||
ShouldRetry: func(err error) bool { return awserrors.Matches(err, "TargetNotConnected", "") },
|
||||
RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 60 * time.Second, Multiplier: 2}).Linear,
|
||||
}.Run(ctx, func(ctx context.Context) (err error) {
|
||||
session, err = s.SvcClient.StartSessionWithContext(ctx, input)
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if 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(session)
|
||||
if err != nil {
|
||||
return nil, *session.SessionId, 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(input)
|
||||
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),
|
||||
s.Region,
|
||||
"StartSession",
|
||||
"", // ProfileName
|
||||
string(sessionParameters),
|
||||
*session.StreamUrl,
|
||||
}
|
||||
return args, *session.SessionId, nil
|
||||
}
|
||||
|
||||
// Start an interactive Systems Manager session with a remote instance via the
|
||||
// AWS session-manager-plugin. To terminate the session you must cancell the
|
||||
// context. If you do not wish to terminate the session manually: calling
|
||||
// StopSession on a instance of this driver will terminate the active session
|
||||
// created from calling StartSession.
|
||||
func (s Session) Start(ctx context.Context, ui packersdk.Ui) error {
|
||||
for ctx.Err() == nil {
|
||||
log.Printf("ssm: Starting PortForwarding session to instance %s", s.InstanceID)
|
||||
args, sessionID, err := s.getCommand(ctx)
|
||||
if sessionID != "" {
|
||||
defer func() {
|
||||
_, err := s.SvcClient.TerminateSession(&ssm.TerminateSessionInput{SessionId: aws.String(sessionID)})
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Error terminating SSM Session %q. Please terminate the session manually: %s", sessionID, err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, "session-manager-plugin", args...)
|
||||
|
||||
ui.Message(fmt.Sprintf("Starting portForwarding session %q.", sessionID))
|
||||
err = localexec.RunAndStream(cmd, ui, nil)
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type AWSPollingConfig
|
||||
package common
|
||||
|
||||
import (
|
||||
@@ -14,7 +12,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
// StateRefreshFunc is a function type used for StateChangeConf that is
|
||||
@@ -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.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,33 +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
|
||||
}
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type StepAMIRegionCopy struct {
|
||||
@@ -24,7 +24,6 @@ type StepAMIRegionCopy struct {
|
||||
|
||||
toDelete string
|
||||
getRegionConn func(*AccessConfig, string) (ec2iface.EC2API, error)
|
||||
AMISkipCreateImage bool
|
||||
AMISkipBuildRegion bool
|
||||
}
|
||||
|
||||
@@ -63,13 +62,7 @@ func (s *StepAMIRegionCopy) DeduplicateRegions(intermediary bool) {
|
||||
}
|
||||
|
||||
func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
|
||||
if s.AMISkipCreateImage {
|
||||
ui.Say("Skipping AMI region copy...")
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
amis := state.Get("amis").(map[string]string)
|
||||
snapshots := state.Get("snapshots").(map[string][]string)
|
||||
intermediary, _ := state.Get("intermediary_image").(bool)
|
||||
@@ -111,7 +104,7 @@ func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) m
|
||||
|
||||
var lock sync.Mutex
|
||||
var wg sync.WaitGroup
|
||||
errs := new(packersdk.MultiError)
|
||||
errs := new(packer.MultiError)
|
||||
wg.Add(len(s.Regions))
|
||||
for _, region := range s.Regions {
|
||||
var regKeyID string
|
||||
@@ -135,7 +128,7 @@ func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) m
|
||||
amis[region] = id
|
||||
snapshots[region] = snapshotIds
|
||||
if err != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, err)
|
||||
errs = packer.MultiErrorAppend(errs, err)
|
||||
}
|
||||
}(region)
|
||||
}
|
||||
@@ -157,7 +150,7 @@ func (s *StepAMIRegionCopy) Run(ctx context.Context, state multistep.StateBag) m
|
||||
|
||||
func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) {
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if len(s.toDelete) == 0 {
|
||||
return
|
||||
@@ -216,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)
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// Define a mock struct to be used in unit tests for common aws steps.
|
||||
@@ -87,7 +87,7 @@ func getMockConn(config *AccessConfig, target string) (ec2iface.EC2API, error) {
|
||||
// Create statebag for running test
|
||||
func tState() multistep.StateBag {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", &packersdk.BasicUi{
|
||||
state.Put("ui", &packer.BasicUi{
|
||||
Reader: new(bytes.Buffer),
|
||||
Writer: new(bytes.Buffer),
|
||||
})
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// stepCleanupVolumes cleans up any orphaned volumes that were not designated to
|
||||
@@ -29,7 +29,7 @@ func (s *StepCleanupVolumes) Cleanup(state multistep.StateBag) {
|
||||
if instanceRaw != nil {
|
||||
instance = instanceRaw.(*ec2.Instance)
|
||||
}
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
if instance == nil {
|
||||
ui.Say("No volumes to clean up, skipping")
|
||||
return
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"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-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/net"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
pssm "github.com/hashicorp/packer/builder/amazon/common/ssm"
|
||||
)
|
||||
|
||||
type StepCreateSSMTunnel struct {
|
||||
AWSSession *session.Session
|
||||
Region string
|
||||
LocalPortNumber int
|
||||
RemotePortNumber int
|
||||
SSMAgentEnabled bool
|
||||
PauseBeforeSSM time.Duration
|
||||
stopSSMCommand func()
|
||||
}
|
||||
|
||||
// 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").(packersdk.Ui)
|
||||
|
||||
if !s.SSMAgentEnabled {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Wait for the remote port to become available
|
||||
if s.PauseBeforeSSM > 0 {
|
||||
ui.Say(fmt.Sprintf("Waiting %s before establishing the SSM session...", s.PauseBeforeSSM))
|
||||
select {
|
||||
case <-time.After(s.PauseBeforeSSM):
|
||||
break
|
||||
case <-ctx.Done():
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
state.Put("sessionPort", s.LocalPortNumber)
|
||||
|
||||
ssmCtx, ssmCancel := context.WithCancel(ctx)
|
||||
s.stopSSMCommand = ssmCancel
|
||||
|
||||
go func() {
|
||||
ssmconn := ssm.New(s.AWSSession)
|
||||
err := pssm.Session{
|
||||
SvcClient: ssmconn,
|
||||
InstanceID: aws.StringValue(instance.InstanceId),
|
||||
RemotePort: s.RemotePortNumber,
|
||||
LocalPort: s.LocalPortNumber,
|
||||
Region: s.Region,
|
||||
}.Start(ssmCtx, ui)
|
||||
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("ssm error: %s", err))
|
||||
}
|
||||
}()
|
||||
|
||||
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) {
|
||||
if !s.SSMAgentEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
if s.stopSSMCommand != nil {
|
||||
s.stopSSMCommand()
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
}
|
||||
@@ -8,34 +8,25 @@ import (
|
||||
"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/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/retry"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
|
||||
"github.com/hashicorp/packer/common/retry"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
type StepCreateTags struct {
|
||||
AMISkipCreateImage bool
|
||||
|
||||
Tags map[string]string
|
||||
SnapshotTags map[string]string
|
||||
Tags TagMap
|
||||
SnapshotTags TagMap
|
||||
Ctx interpolate.Context
|
||||
}
|
||||
|
||||
func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
session := state.Get("awsSession").(*session.Session)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
|
||||
if s.AMISkipCreateImage {
|
||||
ui.Say("Skipping AMI create tags...")
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -81,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())
|
||||
@@ -90,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())
|
||||
@@ -100,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 awserrors.Matches(err, "InvalidAMIID.NotFound", "") || awserrors.Matches(err, "InvalidSnapshot.NotFound", "") {
|
||||
if isAWSErr(err, "InvalidAMIID.NotFound", "") || isAWSErr(err, "InvalidSnapshot.NotFound", "") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type StepDeregisterAMI struct {
|
||||
@@ -24,7 +24,7 @@ func (s *StepDeregisterAMI) Run(ctx context.Context, state multistep.StateBag) m
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
// Add the session region to list of regions will deregister AMIs in
|
||||
regions := append(s.Regions, *ec2conn.Config.Region)
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/retry"
|
||||
"github.com/hashicorp/packer/common/retry"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepGetPassword reads the password from a Windows server and sets it
|
||||
@@ -28,7 +28,7 @@ type StepGetPassword struct {
|
||||
}
|
||||
|
||||
func (s *StepGetPassword) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
// Skip if we're not using winrm
|
||||
if s.Comm.Type != "winrm" {
|
||||
@@ -91,7 +91,7 @@ WaitLoop:
|
||||
}
|
||||
// store so that we can access this later during provisioning
|
||||
state.Put("winrm_password", s.Comm.WinRMPassword)
|
||||
packersdk.LogSecretFilter.Set(s.Comm.WinRMPassword)
|
||||
packer.LogSecretFilter.Set(s.Comm.WinRMPassword)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type StepIamInstanceProfile struct {
|
||||
@@ -25,7 +25,7 @@ type StepIamInstanceProfile struct {
|
||||
|
||||
func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
iamsvc := state.Get("iam").(*iam.IAM)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
state.Put("iamInstanceProfile", "")
|
||||
|
||||
@@ -147,7 +147,7 @@ func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateB
|
||||
|
||||
func (s *StepIamInstanceProfile) Cleanup(state multistep.StateBag) {
|
||||
iamsvc := state.Get("iam").(*iam.IAM)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
var err error
|
||||
|
||||
if s.roleIsAttached == true {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user